#!/usr/bin/env python
# -*- coding: utf-8 -*-
# $Id: __init__.py 9621 2016-04-06 13:36:10Z Eric $
#
# Copyright (c) 2012 Nuwa Information Co., Ltd, All Rights Reserved.
#
# Licensed under the Proprietary License,
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at our web site.
#
# See the License for the specific language governing permissions and
# limitations under the License.
#
# $Author: Eric $
# $Date: 2016-04-06 21:36:10 +0800 (Wed, 06 Apr 2016) $
# $Revision: 9621 $

import sys
import inspect

from Iuno.browser.Request import Request, Response
from Iuno.browser.Request import (
    NavigateError, 
    AccessDeniedError,
    HttpError,
    InvalidHyperlinkError,
    ConnectionError,
    TimeOutError,
    UnknownError,
)

from Iuno.browser.BrowserPanel import BrowserPanel

def factory(clazz, _browser=None):
    """
    Factory method that create correct browser implementation class.

    @param clazz The class you want to create.
    @param _browser Browser type.
    @return Implementation class.
    """
    if _browser:
        m = __import__('%s.%s' % (_browser, clazz), globals(), locals(),
                       [_browser])
        return m.Impl

    # Create implementation by user's platform.
    if sys.platform[:3] == "win":
        import win32api
        import win32con

        # Find the default browser.
        reg = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE,
            "SOFTWARE\Classes\http\shell\open\command")
        default = win32api.RegQueryValue(reg, "")[-1]
        win32api.RegCloseKey(reg)

        if default.lower().find('firefox.exe'):
            return factory(clazz, 'gecko')
        elif (default.lower().find('chrome.exe') or
              default.lower().find('safari.exe')):
            return factory(clazz, 'webkit')
        else:
            return factory(clazz, 'trident')
    else:
        return factory(clazz, 'webkit')

def request(method, url, async=False, engine=None, **kws):
    """
    Constructs and sends a Request with engine implementation.
    
    @parma method HTTP method.
    @param url URL.
    @param async Asynchronous if True, the Request will be handled via celery 
                 worker and not blocked until you access the response.
    @param engine Browser render engine implementation, it can be:
                      'curl': libcurl,
                      'trident': Internet Explorer,
                      'webkit': Safari, Chrome.
    @param **kws Keyword arguments that will be passed to Request object, 
                 please see Request.__init__.
    @return Response object.
    """
    cls = 'AsyncRequest' if async else 'Request'
    req = factory(cls, engine)(url, method=method, **kws)
    req.send()
    return req.response
        
def get(url, async=False, engine=None, **kws):
    """
    Sends a GET request. A simple request('get', ...) wrapper.
    
    @param url URL.
    @param async See request function's async argument.
    @param engine See request function's engine argument.
    @param **kws See request function's kws argument.
    @return Response object.
    """
    return request('get', url, async, engine, **kws)

def post(url, async=False, engine=None, **kws):
    """
    Sends a POST request. A simple request('post', ...) wrapper.
    
    @param url URL.
    @param async See request function's async argument.
    @param engine See request function's engine argument.
    @param **kws See request function's kws argument.
    @return Response object.
    """
    return request('post', url, async, engine, **kws)
    
HTTP_METHOD = {
    'get': get,
    'post': post,
}
    
def fetch(url, engine=None, options={}):
    """
    Fetch a response, a general API wrapper for request.
    It is used for backward compatible with other code bases, but also an easy 
    way to pass options to request API.
    
    @param url URL.
    @param engine See request function's engine argument.
    @param options All options you want to pass to request or browser's render
                   engine server. Or some configuration parameters are passed 
                   via keyword arguments, some are filled into config keyword 
                   argument.
    @return Response.
    """
    # Preprocess.    
    kws = dict([(arg, options[arg]) 
                for arg in inspect.getargspec(Request.__init__)[0]
                if arg in options])
        
    method = kws.pop('method', 'get')
    if 'get' in options:        
        kws['params'] = options['get']
    if 'post' in options:
        method = 'post'
        kws['data'] = options['post']
    
    kws['config'] = dict([(key, options[key]) for key in options 
                          if key not in kws])
    
    async = options.get('async', False)
    return request(method, url, engine=engine, async=async, **kws)
