#!/usr/bin/env python3

import argparse
import sys
import urllib

import pyperclip
from selenium import webdriver

import gettitle.constants
import gettitle.exceptions
import gettitle.handles


def get_args():
    p = argparse.ArgumentParser()
    p.add_argument(
        'urls',
        metavar='url',
        type=str,
        nargs='+',
        help="url(s) of the webpage",
    )
    p.add_argument(
        '-m', '--markdown',
        action='store_true',
        help="output with markdown format",
    )
    p.add_argument(
        '-d', '--debug',
        action='store_true',
        help="print out webpage source code and title for debugging",
    )

    return p.parse_args()


def combine_title_and_url(args, title, url):
    title = title.strip().replace('\n', ' ')
    url = url.strip()

    if args.markdown:
        title = '[' + title.replace('[', r'\[').replace(']', r'\]') + ']'
        url = '(' + url + ')'
        s = '{title}{url}\n'
    else:
        s = '{title}\n{url}\n'

    return s.format(title=title, url=url)


def check_and_reconstruct_url(url):
    url = url.strip()
    url_components = urllib.parse.urlparse(url)

    if not url:
        raise gettitle.exceptions.EmptyUrlError
    elif not url_components.scheme:
        url = "{}://{}".format('http', url)
        url_components = urllib.parse.urlparse(url)
    elif url_components.scheme not in ('http', 'https'):
        url_components = url_components._replace(scheme='http')

    return urllib.parse.urlunparse(url_components)


def visit_with_js_browser(js_br, url, debug=False):
    page, title, real_url = None, None, None

    try:
        js_br.visit(url)
    except:
        gettitle.handles.handle_error(sys.exc_info()[0], debug)
    else:
        page = bs(js_br.body(), 'lxml')
        title = html.unescape(page.title.string)
        real_url = js_br.url()

        if debug:
            print(page.prettify())

    if page is None:
        raise RuntimeError('page is None')

    return title, real_url


def visit_with_no_js_browser(br, url, debug=False):
    page, title, real_url = None, None, None

    try:
        br.open(url)
    except requests.exceptions.InvalidURL:
        print("Invalid URL")
    except requests.exceptions.ConnectionError as e:
        print(e)
        gettitle.handles.handle_error(e, debug, url=url)
        raise gettitle.exceptions.ConnectionError
    except Exception as e:
        gettitle.handles.handle_error(e, debug)
    else:
        page = br.parsed
        real_url = br.url
        try:
            title = html.unescape(page.title.string)
        except:
            raise

    if gettitle.constants.sites['ptt'] in real_url:
        form = br.get_form(action="/ask/over18")
        if form:
            br.submit_form(form, submit=form['yes'])
            page = br.parsed
            real_url = br.url
            title = html.unescape(page.title.string)

    if page is None:
        raise RuntimeError('page is None')

    if debug:
        print(page.prettify())

    return title, real_url


def get_title_and_url(br, url, debug=False):
    try:
        checked_url = check_and_reconstruct_url(url)
    except gettitle.exceptions.EmptyUrlError:
        raise

    try:
        title, url = visit_with_no_js_browser(br['no_js'], checked_url, debug)
    except gettitle.exceptions.ConnectionError:
        raise
    except:
        try:
            title, url = visit_with_js_browser(br['js'], checked_url, debug)
        except:
            raise

    return title.strip(), url.strip()


def get_titles_and_urls(br, args):
    titles_and_urls = []

    for url_from_user in args.urls:
        try:
            title, url = get_title_and_url(br, url_from_user, args.debug)
        except:
            continue
        else:
            s = combine_title_and_url(args, title, url)
            titles_and_urls.append(s)

        if args.debug:
            print(title, type(title))

    return titles_and_urls


def print_titles_and_urls(titles_and_urls):
    if titles_and_urls:
        print('')
        print('\n'.join(titles_and_urls))


def copy_result_to_clipboard_for_users(titles_and_urls, debug=False):
    '''
    This function currently only support Linxu users with `xclip` installed.
    '''
    # [:-1] to prevent the last '\n' to be copied.
    text = '\n'.join(titles_and_urls)[:-1]
    try:
        pyperclip.copy(text)
    except:
        raise
    else:
        print("Copied result to clipboard.")


def main():
    args = get_args()

    try:
        browser = webdriver.PhantomJS()
    except Exception as e:
        gettitle.handles.handle_error(e)
    else:
        titles_and_urls = get_titles_and_urls(browser, args)
    finally:
        browser.quit()

    print_titles_and_urls(titles_and_urls)
    copy_result_to_clipboard_for_users(titles_and_urls, args.debug)


if __name__ == '__main__':
    status = main()
    sys.exit(status)

@@ -3060,24 +3060,29 @@
 e_and_url(br
+owser
 , url, debug
@@ -3086,24 +3086,24 @@
 bug=False):%0A
-
     try:%0A   
@@ -3246,38 +3246,32 @@
 rl = visit_with_
-no_js_
 browser(br%5B'no_j
@@ -3268,17 +3268,13 @@
 r(br
-%5B'no_js'%5D
+owser
 , ch
@@ -3306,194 +3306,64 @@
 ept 
-gettitle.exceptions.ConnectionError:%0A        raise%0A    except:%0A        try:%0A            title, url = visit_with_js_browser(br%5B'js'%5D, checked_url, debug)%0A        except:%0A            raise
+Exception as e:%0A        gettitle.handles.handle_error(e)
 %0A%0A  
@@ -3426,16 +3426,21 @@
 _urls(br
+owser
 , args):
@@ -3560,16 +3560,21 @@
 d_url(br
+owser
 , url_fr
@@ -3600,32 +3600,42 @@
 )%0A        except
+ Exception
 :%0A            co

Change name for functions get_title(s)_and_url(s)