#!/usr/bin/python3
"""
Write good code and walk away
"""

import argparse
import json
import logging
import os
import sys
import textwrap
import threading
import urllib.parse
import warnings
import webbrowser

import requests
import urwid

try:
    from lxml import etree
except ImportError:
    import xml.etree.ElementTree as etree

from util.scroll import ScrollBar, Scrollable
import Search.bing as bing
import Search.duck as duck
import Search.google as google
import Search.google_scholar as scholar

# ADDITIONS: Search engine module
engines = {
    'google': google,
    "duck": duck,
    'bing': bing,
    'g-scholar': scholar
}
GIT = 'https://www.github.com/steve-tyler/ISearch.git'

ENCODING = sys.getfilesystemencoding()
# Warn if encoding is something we've never seen
if ENCODING != 'utf-8':
    warnings.warn('The program has not been tested with any encoding'
                  f'other than utf-8. Your system encoding is {ENCODING} Proceed at your own caution')
TERM = os.get_terminal_size().lines - 6

__version__ = '0.2.0'


class DownloadException(Exception):
    """
    Base class for download file exceptions
    """

    pass


class Cmd:
    def __init__(self, query: str, engine, pprint_json=False, duck_api=False,
                 pprint_xml=False, colours=True, **kwargs):
        """
        ISearch cmd class
        """
        self.kwargs = kwargs
        self.engine = engines.get(engine)
        self.query = query
        self.colours = colours
        if duck_api and 'Duck' in self.engine.__name__:
            data = self.engine.Search(query).handle_api()
            print(data)
            quit()
        if pprint_json:
            self.printer = self.pprint_json
        elif pprint_xml:
            self.printer = self.pprint_xml
        else:
            self.printer = self.pprint_cmd

    def cmd_search(self):
        try:
            if self.query.strip('\\').startswith("!") and 'DuckDuckGo' in self.engine.__name__:
                # A bang search
                self.engine.Search(self.query.strip('\\'), **self.kwargs).handle_bang()
                quit(0)
            else:
                self.results = self.engine.Search(self.query, **self.kwargs)
        except self.engine.NoInternetError:
            quit(1)
        except Exception as e:
            logging.exception(e, exc_info=False)
            quit(1)

    def fetch_next(self):
        """
        Fetch next results
        :return: a list  :type whose elements are a dict :type containing
        a title, link, and  text
        """
        if not hasattr(self, 'results'):
            self.cmd_search()
        try:
            return self.results.next()
        except ConnectionError as ce:
            quit(1)
        except Exception as e:
            logging.exception(e, exc_info=False)
            quit(1)

    def pprint_cmd(self):
        col = os.get_terminal_size().columns - 4
        width = col if col < 190 else 145
        if self.colours:
            red = '\033[91m'
            bold = '\033[1m'
            blue = '\033[94m'
            purple = '\033[95m'
            green = '\033[92m'
            yellow = '\033[93m'
            endc = '\033[0m'
        else:
            red = ''
            bold = ''
            blue = ''
            purple = ''
            green = ''
            yellow = ''
            endc = ''

        store = ''
        for items in self.fetch_next():
            if int(items['rank']) < 10:
                space = '.  '
            else:
                space = '. '
            store += bold + items['rank'] + space + red + items['title'].lstrip(' ') + endc + '\n'
            if items.get('time'):
                store += purple + '    ' + items['time'] + endc + '\n'
            store += blue + '    ' + items['link'] + endc + '\n'
            if items.get('info'):
                store += green + '    ' + items['info'] + endc + '\n'
            if items.get('pdf_link'):
                store += yellow + '    ' + items['pdf_link'] + endc + '\n'

            for item in textwrap.wrap(items['text'], width=width):
                store += "    " + item + "\n"
            store += "\n"

        print(store)
        return ''

    def pprint_json(self):
        """
        Print json output to the terminal
        """
        # Encode and decode to ensure support for unicode characters.
        dump = json.dumps(self.fetch_next(), indent=4, ensure_ascii=False).encode(ENCODING)
        print(dump.decode(ENCODING))

    def pprint_xml(self):
        xml_p = etree.Element('root', encoding='utf-8')
        # Create a xml document
        for items in self.fetch_next():
            result = etree.Element('result', attrib={'rank': items['rank']})
            etree.SubElement(result, "title").text = items['title']
            etree.SubElement(result, "link").text = items['link']
            etree.SubElement(result, "text").text = items['text']
            xml_p.append(result)
        # Specify the encoding and decoding to add support for unicode characters
        print(etree.tostring(xml_p, pretty_print=True, xml_declaration=True, encoding='utf-8').decode('utf-8'))


progress_bar = urwid.ProgressBar('a', 'b')


class InteractiveCmd:
    def __init__(self):
        global progress_bar
        self.palette = (
            ('titlebar', 'dark red,bold,underline', 'black'),
            ('quit', 'light red,bold,underline', 'black'),

            ('alert', 'dark red,bold,blink', ''),
            ('info', 'light blue,bold,blink', ''),

            ('query', 'bold', 'black'),

            ('google', 'light red,bold', ''),
            ('duck', 'light green,bold', ''),
            ('bing', 'light blue,bold', ''),
            ('scholar', 'light magenta,bold', ''),

            ('title', 'light red, bold', ''),
            ('link', 'light blue,underline', ''),

            ('download_title', 'light green, bold,underline', ''),
            ('download_edt', 'bold', ''),
            ('download_btn', 'dark magenta,bold', ''),
            ('color', 'light green,bold', ''),

            ('time', 'light green', ''),
            ('pdf_link', 'yellow', ''),
            ('result_info', 'brown', '')
        )
        # Header
        self.header = urwid.Text(('titlebar', u'ISearch\u26A1'), align='center')

        # Body
        self.result_bar = urwid.Text(u"Input a query and press enter.\nResults will be displayed \u2193 "
                                     u"\nPress F1 for shortcuts")
        padding = urwid.Padding(self.result_bar, left=2, right=2)
        self.line_box = urwid.BoxAdapter(urwid.LineBox(ScrollBar(Scrollable(padding)), title='Result bar'),
                                         height=TERM)
        # Options for search engines.

        # ADDITIONS: Search engine options
        opt_grp = []
        self.google_opt = urwid.RadioButton(opt_grp, 'Google', on_state_change=self.det_search_module, user_data=None)
        google_opt = urwid.AttrMap(self.google_opt, 'google')
        self.bing_opt = urwid.RadioButton(opt_grp, 'Bing', on_state_change=self.det_search_module, user_data=None)
        bing_opt = urwid.AttrMap(self.bing_opt, 'bing')
        self.duck_opt = urwid.RadioButton(opt_grp, 'DuckDuckGo', state=True, on_state_change=self.det_search_module,
                                          user_data=None)

        duck_opt = urwid.AttrMap(self.duck_opt, 'duck')
        self.scholar_opt = urwid.RadioButton(opt_grp, 'Google Scholar',
                                             on_state_change=self.det_search_module,
                                             user_data=None)
        scholar_opt = urwid.AttrMap(self.scholar_opt, 'scholar')
        opt = urwid.GridFlow([bing_opt, duck_opt, google_opt, scholar_opt], 20, 4, 1, align='center')

        # Next button
        next_btn = urwid.GridFlow([urwid.Button('Next', on_press=self.next)], 8, 0, 0, align='center')
        # Previous button
        prev_btn = urwid.GridFlow([urwid.Button('Previous', on_press=self.previous)], 12, 0, 0, align='center')
        # Download options
        download_title = urwid.Text(('download_title', "Download a File [F8]"), align='center')
        self.download_url = urwid.Edit("URL >> ")
        # Save the file in Downloads directory. unless explicitly told otherwise.
        self.download_path = urwid.Edit('Path >>', edit_text=os.environ['HOME'] + "/Downloads")
        download_btn = urwid.Button("Download", on_press=self.download_thread)

        download_opt = urwid.LineBox(
            urwid.Pile([download_title,
                        urwid.AttrMap(self.download_url, 'download_edt'),
                        urwid.Divider(),
                        urwid.AttrMap(self.download_path, 'download_edt'),
                        urwid.Divider(),
                        urwid.AttrMap(urwid.GridFlow([download_btn], 13, 0, 0, align='center'), 'download_btn')
                        ])
        )
        btn_pile = urwid.Pile([prev_btn, urwid.Divider(), next_btn])
        self.info_bar = urwid.Text('')

        body = urwid.Columns([('weight', 5, self.line_box),
                              urwid.Pile([urwid.LineBox(opt, title='Search Engines'),
                                          urwid.Divider(),
                                          urwid.LineBox(btn_pile),
                                          urwid.Divider(),
                                          download_opt,
                                          urwid.Divider(),
                                          urwid.LineBox(self.info_bar, title='Info bar'),
                                          urwid.Divider(),
                                          urwid.LineBox(progress_bar, title='Progress bar')
                                          ])
                              ])

        # Footer
        self.query = urwid.Edit('Query>>> ')
        column_bar = urwid.Columns([('weight', 5, urwid.LineBox(urwid.AttrMap(self.query, 'query'))),
                                    urwid.Divider()],
                                   dividechars=6)
        # Exit button with Grid for compactness.
        exit_btn = urwid.GridFlow([urwid.AttrMap(urwid.Button("Exit", on_press=self.exit), 'quit')],
                                  cell_width=8,
                                  h_sep=0,
                                  v_sep=0,
                                  align='center')
        footer_pile = urwid.Pile([column_bar, urwid.Divider(), exit_btn])

        # Assemble widgets
        # Set the focus on the footer
        self.frame = urwid.Frame(header=self.header, body=urwid.Filler(body, valign='top', top=1, bottom=1),
                                 footer=footer_pile,
                                 focus_part='footer')

    def download_thread(self, *args):
        """Start a thread to download a file"""
        self.thread = threading.Thread(target=self.download_file)
        self.thread.daemon = False
        self.thread.start()

    def download_file(self, *args):
        """Download a file from the internet"""
        global loop, progress_bar
        if not self.download_url.get_edit_text().strip(""):
            self.info_bar.set_text(('alert', "ERROR:No url provided"))
        else:
            url = self.download_url.get_edit_text()
            try:
                # Stream the data we don't want adding a 500 mb file to memory.
                data = requests.get(url, stream=True)
                # Raise an error if the status code lies above 400
                data.raise_for_status()
            except Exception as e:
                self.info_bar.set_text(('alert', e.__str__()))
            else:
                _path = self.download_path.get_edit_text()
                try:
                    # Create a file and then close, like the touch program
                    open(_path, mode='x').close()
                except IsADirectoryError:
                    # IF the path ends with / it becomes a directory.
                    os.makedirs(_path, exist_ok=True)
                except (FileExistsError, FileNotFoundError) as e:
                    self.info_bar.set_text(('alert', e.__str__()))
                if os.path.isfile(_path):
                    path = _path
                elif os.path.isdir(_path):
                    # Get the filename from the last part url or if no filename set it to index.html
                    # BUG: Sometimes it may save the file using the ip address
                    filename = urllib.parse.urlsplit(self.download_url.get_edit_text()).path.rsplit("/")[-1:][0] \
                               or "index.html"
                    path = _path + "/" + filename
                else:
                    raise DownloadException("Path is malformed")
                self.info_bar.set_text(("color", 'Downloading from {}'.format(url)))
                try:
                    size = int(data.headers.get('Content-Length') or len(data.content))
                    download = 0
                    with open(path, "wb") as wfile:
                        # Chunk everything in 10 mb files
                        for chunk in data.iter_content(10485760):
                            download += 10485760
                            rem = download // size
                            progress_bar.set_completion(rem)
                            loop.draw_screen()
                            wfile.write(chunk)
                    progress_bar.set_completion(100)
                except Exception as e:
                    self.result_bar.set_text(('alert', e.__str__()))
                else:
                    self.info_bar.set_text(("color", 'File saved at {}'.format(path)))

    def previous(self, *args):
        """Fetch previous results"""
        tbp = []
        self.det_search_module()
        if hasattr(self, 'searcher'):
            try:
                for items in self.searcher.previous():
                    tbp.append(('title', items['rank'] + '.' + items['title'] + '\n'))
                    if items.get('time'):
                        tbp.append(('time', items['time'] + '\n'))
                    tbp.append(('link', items['link'] + '\n'))
                    if items.get('info'):
                        tbp.append(('result_info', items['info'] + '\n'))
                    if items.get('pdf_link'):
                        tbp.append(('pdf_link', items['pdf_link'] + "\n"))
                    tbp.append(items['text'] + '\n\n')
                self.result_bar.set_text(tbp)
            except ConnectionError:
                self.info_bar.set_text(('alert', "ERROR:No Internet connection detected"))
            except self.search_m.NoResultsError:
                self.info_bar.set_text(('alert', 'No previous results'))
        else:
            self.info_bar.set_text(('alert', 'No results to go back to'))

    def next(self, *args):
        """
        Fetch next results
        :return:
        """
        tbp = []
        self.det_search_module()
        if hasattr(self, 'searcher'):
            try:
                for items in self.searcher.next():
                    tbp.append(('title', items['rank'] + '.' + items['title'] + '\n'))
                    if items.get('time'):
                        tbp.append(('time', items['time'] + '\n'))
                    tbp.append(('link', items['link'] + '\n'))
                    if items.get('info'):
                        tbp.append(('result_info', items['info'] + '\n'))
                    if items.get('pdf_link'):
                        tbp.append(('pdf_link', items['pdf_link'] + "\n"))
                    tbp.append(items['text'] + '\n\n')
                self.result_bar.set_text(tbp)
            except ConnectionError:
                self.info_bar.set_text(('alert', "ERROR:No Internet connection detected"))
            except self.search_m.ExhaustedResultsError:
                self.info_bar.set_text(("alert", f"That's all from {self.search_m.__name__}\n"
                                                 u"No more results :\\"))
            except Exception as e:
                self.info_bar.set_text(('alert', e.__str__()))
        else:
            self.search()

    def det_search_module(self, *args):
        """
        Determine search module to use.
        By checking, which radiobutton state has been set
        to True.
        """
        if self.google_opt.state:
            self.search_m = google
        elif self.bing_opt.state:
            self.search_m = bing
        elif self.duck_opt.state:
            self.search_m = duck
        elif self.scholar_opt.state:
            self.search_m = scholar
        # ADDITIONS:Search engine state

    def search(self, *args):
        """
        Fetch and print results
        """
        # Clear whatever info is on the info bar
        self.info_bar.set_text('')
        query = self.query.get_edit_text()
        # if query is just spaces ....
        if query.strip() is '':
            self.info_bar.set_text(('alert', 'ERROR:Input a value into the query box'))
        else:
            self.det_search_module()
            tbp = []
            if query.strip(" ").startswith("!") or query.strip('').startswith("/") \
                    and "Duck" in self.search_m.__name__:
                # DuckDuckGo bang request
                self.search_m.Search(query).handle_bang()
                self.result_bar.set_text([("info", "Now that's a !bang\n"),
                                          ('', "Check out https://api.duckduckgo.com/bang for more info")])
            else:
                # Normal request
                self.line_box.set_title(self.search_m.__name__ + " results for '{query}'".format(query=query))
                try:
                    self.searcher = self.search_m.Search(query)
                    for items in self.searcher.next():
                        tbp.append(('title', items['rank'] + '.' + items['title'] + '\n'))
                        if items.get('time'):
                            tbp.append(('time', items['time'] + '\n'))
                        tbp.append(('link', items['link'] + '\n'))
                        if items.get('info'):
                            tbp.append(('result_info', items['info'] + '\n'))
                        if items.get('pdf_link'):
                            tbp.append(('pdf_link', items['pdf_link'] + "\n"))
                        tbp.append(items['text'] + '\n\n')
                    self.result_bar.set_text(tbp)
                except ConnectionError:
                    self.info_bar.set_text(('alert', "ERROR:No Internet connection detected"))
                except self.search_m.ExhaustedResultsError:
                    self.info_bar.set_text(("alert", f"That's all from {self.search_m.__name__}\n"
                                                     u"No more results :\\"))
                except Exception as e:
                    self.info_bar.set_text(('alert', e.__str__()))

    def exit(self, nothing=None):
        """
        Exit mainloop
        """
        raise urwid.ExitMainLoop()

    def handle_input(self, keypress):
        """
        Handle  unknown input
        :param keypress: Key pressed
        :return:
        """
        if keypress == 'enter':
            self.search()
        if keypress == 'esc':
            self.exit()
        if keypress == 'f8':
            # Shortcut for Download options
            self.download_thread()
        if keypress == 'f1':
            # Show help
            self.show_help()
        if keypress == 'f4':
            # Open the project's github page
            webbrowser.open(GIT)
        if keypress == 'f3':
            self.info_bar.set_text('')

    def show_help(self, key=None):
        help_msg = [
            """
            Press       'F1' to show this help
            Press       'F3' to clear info bar
            Press       '""", ("titlebar", "F4"), """' to open the project in github.com.
            Press       'F8' to download the url present in the Download bar
            
            Press       'ESC' to exit.
            Press       'enter' to perform a search. 
            """
        ]
        self.result_bar.set_text(help_msg)


interactive = InteractiveCmd()
loop = urwid.MainLoop(interactive.frame, interactive.palette, unhandled_input=interactive.handle_input)


def main():
    parser = argparse.ArgumentParser(prog='ISearch',
                                     description="ISearch command line options",
                                     epilog="Submit bugs at {}".format(GIT),
                                     formatter_class=argparse.RawTextHelpFormatter,
                                     allow_abbrev=True
                                     )
    # Debug options
    parser.add_argument('-d', '--debug', action='store_true',
                        help='Enable debugging mode')
    # ISearch interactive mode
    parser.add_argument("-i", '--interactive', action='store_true',
                        help='Enter ISearch interactive mode')
    # Proxy support
    parser.add_argument("-p", '--proxy', help='Specify proxy to use'
                                              '\nFormat is [<proxy-scheme>://]<proxy-host>[:<proxy-port>'
                                              '\nScheme is one of "http", "socks", "socks4", "socks5" '
                                              '\nEg http://foobar.com:99 is a valid proxy format\n\n',
                        metavar='SERVER')

    sbp = parser.add_subparsers(dest='s_name', help="", metavar='')

    # Bing sub-options
    bing_p = sbp.add_parser("bing", description="Bing search in ISearch",

                            help='Bing Search in ISearch\n\n',
                            formatter_class=argparse.RawTextHelpFormatter,
                            epilog="Submit bugs at {}".format(GIT),
                            allow_abbrev=True
                            )
    bing_p.add_argument('query', help='Search query')
    bing_p.add_argument('-d', "--disable-colours", action='store_true',
                        help="Disable colour output [only when printing to cmd]\n\n")
    bing_p.add_argument("-c", dest='tld', metavar='country', help='Top level domain to use\n\n')
    bing_p.add_argument('-j', '--json', action='store_true', help='Output in json format')
    bing_p.add_argument('-x', '--xml', action='store_true', help='Output in xml format\n\n')
    bing_p.add_argument('-l', '--lang', type=str, default='en', help='Language to return results in [default:en]',
                        metavar='')
    bing_p.add_argument('-s', '--safe', type=int, choices=[0, 1, 2], default=1, metavar='',
                        help='Safe search level\nOptions are:'
                             '\n\t0:No safe search'
                             '\n\t1:Moderate safe search'
                             '\n\t2:Strict safe search\n\n')
    bing_p.add_argument("-n", '--num', type=int, default=10, help="print 'N' amount of results [from 0-50]",
                        metavar='')
    bing_p.add_argument('-p', '--page', metavar='', type=int, default=1, help="Fetch results from the n'th page\n\n")
    bing_p.add_argument('-t', '--time', metavar='span', help='Filer results by age\nFormats are:'
                                                             '\n\tDay[results for that day], Month[results from this '
                                                             'month],Year[results from this year]\n '
                                                             '\tOr Dates separated in YYYY-MM-DD...YYYY-MM-DD or '
                                                             '\n\tFor specific dates,use the format YYYY-MM-DD')
    # DuckDuckGo Options
    duck_p = sbp.add_parser("duck", description="DuckDuckGo search in ISearch",
                            help="DuckDuckGo Search in ISearch\n\n",
                            formatter_class=argparse.RawTextHelpFormatter,
                            epilog="To perform !bang requests(because they are amazing) add a '\\' before the bang "
                                   "if weird things happen with just a !\n"
                                   "This is because bash and zsh have their own !bang implementations\n"
                                   "(Which are also cool)\n\n"
                                   "Submit bugs at {}".format(GIT),
                            allow_abbrev=True
                            )
    duck_p.add_argument('query', help='Search query')
    duck_p.add_argument('-d', "--disable-colours", action='store_true',
                        help="Disable colour output [ only to when printing to cmd ]\n\n")
    duck_p.add_argument('-a', '--api', action='store_true',
                        help='Fetch results from DuckDuckGo api\n'
                             '(Note do not use this for deep queries, results will be null)\n\n')
    duck_p.add_argument('-c', metavar='country', dest='country',
                        help="Region to search from [default wt-wt -'Global']\n\n")
    duck_p.add_argument('-j', '--json', action='store_true', help='Output in json format')
    duck_p.add_argument('-x', '--xml', action='store_true', help='Output in xml format\n\n')
    duck_p.add_argument("-n", '--num', type=int, default=10, help="print 'N' amount of results [range:0-30]\n\n",
                        metavar=' ')
    duck_p.add_argument('-p', '--page', type=int, default=1, help="Fetch results from n'th page\n\n", metavar='')
    duck_p.add_argument('-s', '--safe', metavar='', type=int, choices=[-2, -1, 1],
                        help='Safe search options valid options are:'
                             '\n\t 1:On'
                             '\n\t-1:Moderate [default]'
                             '\n\t-2:Off')

    # Google sub-options
    google_p = sbp.add_parser("google", description="Google search in ISearch",
                              help='Google Search in ISearch\n\n',
                              formatter_class=argparse.RawTextHelpFormatter, epilog=
                              "For this to work we, require selenium module, and a chrome-webdriver(if using Chrome)\n"
                              'Fetch the latest from  http://chromedriver.storage.googleapis.com/index.html\n'
                              'Chrome/Chromium works faster than Firefox... \n\n'
                              f"Submit bugs at {GIT}")

    google_p.add_argument("query", help='Search query')
    google_p.add_argument('-d', "--disable-colours", action='store_true',
                          help="Disable colour output[only when printing to cmd]\n\n")
    google_p.add_argument('-c', dest='tld', metavar='country',
                          help="Country Top level domain to use\n\n")
    google_p.add_argument('-j', '--json', action='store_true', help='Output in json format')
    google_p.add_argument('-x', '--xml', action='store_true', help='Output in xml format\n\n')
    google_p.add_argument('-p', '--page', help="Fetch results from the n'th page", metavar='',
                          type=int, default=1)
    google_p.add_argument("-n", '--num', help="Fetch 'N' amount of results [default:10]\n\n",
                          type=int, default=10, metavar='')
    google_p.add_argument('-l', '--lang', help="Language to return results in [default:en]\n\n", type=str, default='en',
                          metavar='')
    google_p.add_argument('-t', '--time', help='Limit search to files indexed in:'
                                               '\n\t d:The previous 24 hours'
                                               '\n\t w:The previous week'
                                               "\n\t m:The previous month [mn] the previous 'n' number of months"
                                               '\n\t y:The previous year\n\n', metavar='')
    google_p.add_argument('-u', '--unfilter', action='store_true', help='Show unfiltered search results')
    google_p.add_argument('-X', '--exact', action='store_true', help='Disable spelling correction')

    parser.add_argument("-v", "--version", action="version", version=__version__)
    # ADDITIONS: CommandLine Search options
    scholar_p = sbp.add_parser("g-scholar", description="Google Scholar search in ISearch",
                               help='Google Scholar Search in ISearch\n\n',
                               formatter_class=argparse.RawTextHelpFormatter, epilog='Google Scholar ,Your one '
                                                                                     'stop shop for all nerdy documents\n'
                                                                                     f"Submit bugs at {GIT}")
    scholar_p.add_argument('query', help='Search query')
    scholar_p.add_argument('-d', "--disable-colours", action='store_true',
                           help="Disable colour output[only when printing to cmd]\n\n")
    scholar_p.add_argument('-j', '--json', action='store_true', help='Output in json format')
    scholar_p.add_argument('-x', '--xml', action='store_true', help='Output in xml format\n\n')
    scholar_p.add_argument('-p', '--page', help="Fetch results from the n'th page", metavar='',
                           type=int, default=1)
    scholar_p.add_argument("-n", '--num', help="Fetch 'N' amount of results [default:10]\n\n",
                           type=int, default=10, metavar='')
    scholar_p.add_argument('-l', '--lang', help="Language to return results in [default:en]\n\n", type=str,
                           default='en',
                           metavar='')
    scholar_p.add_argument('-s', '--sort', help='Sort by relevance', action='store_true')
    scholar_p.add_argument('-t', '--time', help='Return files indexed in:'
                                                "\nYears eg '2015' is a valid time", metavar='')

    options = parser.parse_args()

    if options.debug:
        logging.basicConfig(format='%(asctime)s %(module)s  %(levelname)s 	%(message)s', level=logging.DEBUG)
    if options.proxy:
        proxy = options.proxy
    else:
        proxy = None

    if options.interactive:
        logging.disable(100)

        loop.run()

    elif options.s_name == 'google':
        query = options.query
        inst_c = Cmd(query, engine=options.s_name, pprint_json=options.json, pprint_xml=options.xml,
                     colours=not options.disable_colours,
                     # Other info
                     country=options.tld, exact=options.exact, num=options.num, page=options.page, hl=options.lang,
                     as_qdr=options.time, proxy=proxy, filter=options.unfilter
                     )
        inst_c.printer()

    elif options.s_name == 'duck':
        query = options.query
        inst_c = Cmd(query, engine=options.s_name, pprint_json=options.json, pprint_xml=options.xml,
                     colours=not options.disable_colours, duck_api=options.api,
                     # Other options
                     num=options.num, page=options.page, country=options.country, safesearch=options.safe,
                     proxy=proxy)
        inst_c.printer()

    elif options.s_name == 'bing':
        query = options.query
        inst_c = Cmd(query, engine=options.s_name, pprint_json=options.json, pprint_xml=options.xml,
                     colours=not options.disable_colours,
                     # Again, other options
                     country=options.tld, language=options.lang, num=options.num, page=options.page,
                     safe_search=options.safe, freshness=options.time, proxy=proxy)
        inst_c.printer()
    elif options.s_name == 'g-scholar':
        inst_c = Cmd(options.query, engine=options.s_name, pprint_json=options.json, pprint_xml=options.xml,
                     colours=not options.disable_colours,
                     # Again, other options
                     hl=options.lang, num=options.num, page=options.page,
                     sort_by_date=options.sort, from_date=options.time, proxy=proxy)
        inst_c.printer()
    else:
        parser.print_help()


if __name__ == '__main__':
    main()
