#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#     Copyright (C) 2014 KenV99
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import sys
import traceback
import requests
import urllib2
import httplib
from urlparse import urlparse
import socket
from resources.lib.taskABC import AbstractTask, KodiLogger, notify
from resources.lib.utils.poutil import KodiPo
kodipo = KodiPo()
_ = kodipo.getLocalizedString
__ = kodipo.getLocalizedStringId

class TaskHttp(AbstractTask):
    tasktype = 'http'
    variables = [
        {
            'id':u'http',
            'settings':{
                'default':u'',
                'label':u'HTTP string (without parameters)',
                'type':'text'
            }
        },
        {
            'id':u'user',
            'settings':{
                'default':u'',
                'label':u'user for Basic Auth (optional)',
                'type':'text'
            }
        },
        {
            'id':u'pass',
            'settings':{
                'default':u'',
                'label':u'password for Basic Auth (optional)',
                'type':'text',
                'option':u'hidden'
            }
        },
        {
            'id': u'request-type',
            'settings': {
                'default': u'GET',
                'label': u'Request Type',
                'type': u'labelenum',
                'values': [u'GET', u'POST', u'POST-GET', u'PUT', u'DELETE', u'HEAD', u'OPTIONS']
            }
        },
        {
            'id': u'content-type',
            'settings': {
                'default': u'application/json',
                'label': u'Content-Type (for POST or PUT only)',
                'type': u'labelenum',
                'values': [u'application/json', u'application/x-www-form-urlencoded', u'text/html', u'text/plain']
            }
        }
    ]

    def __init__(self):
        super(TaskHttp, self).__init__(name='TaskHttp')
        self.runtimeargs = u''

    @staticmethod
    def validate(taskKwargs, xlog=KodiLogger.log):
        o = urlparse(taskKwargs['http'])
        if o.scheme != '' and o.netloc != '':
            return True
        else:
            xlog(msg=_('Invalid url: %s') % taskKwargs['http'])
            return False

    def sendRequest(self, session, verb, url, postget=False):
        if (postget or verb == 'POST' or verb == 'PUT') and '??' in url:
            url, data = url.split(u'??', 1)
            try:
                data = data.encode('utf-8', 'replace')
            except UnicodeEncodeError:
                pass
            if postget:
                data = None
        else:
            data = None
        req = requests.Request(verb, url, data=data)
        try:
            prepped = session.prepare_request(req)
        except httplib.InvalidURL as e:
            err = True
            msg = unicode(e, 'utf-8')
            return err, msg
        if verb == 'POST' or verb == 'PUT':
            prepped.headers['Content-Type'] = self.taskKwargs['content-type']
        try:
            pu = prepped.url.decode('utf-8')
        except (AttributeError, UnicodeDecodeError):
            pu = u''
        try:
            pb = prepped.body.decode('utf-8')
        except (AttributeError, UnicodeDecodeError):
            pb = u''
        msg = u'Prepped URL: %s\nBody: %s' % (pu, pb)
        sys.exc_clear()
        try:
            resp = session.send(prepped, timeout=20)
            msg += u'\nStatus: %s' % resp.status_code
            resp.raise_for_status()
            err = False
            if resp.text == '':
                respmsg = u'No response received'
            else:
                respmsg = resp.text.decode('unicode_escape', 'ignore')
            msg += u'\nResponse for %s: %s' %(verb, respmsg)
            resp.close()
        except requests.ConnectionError:
            err = True
            msg = _(u'Requests Connection Error')
        except requests.HTTPError as e:
            err = True
            msg = u'%s: %s' %(_(u'Requests HTTPError'), str(e))
        except requests.URLRequired as e:
            err = True
            msg = u'%s: %s' %(_(u'Requests URLRequired Error'), str(e))
        except requests.Timeout as e:
            err = True
            msg = u'%s: %s' %(_(u'Requests Timeout Error'), str(e))
        except requests.RequestException as e:
            err = True
            msg = u'%s: %s' %(_(u'Generic Requests Error'), str(e))
        except urllib2.HTTPError, e:
            err = True
            msg = _(u'HTTPError = ') + unicode(e.code)
        except urllib2.URLError, e:
            err = True
            msg = _(u'URLError\n') + unicode(e.reason)
        except httplib.BadStatusLine:
            err = False
            self.log(msg=_(u'Http Bad Status Line caught and passed'))
        except httplib.HTTPException, e:
            err = True
            msg = _(u'HTTPException')
            if hasattr(e, 'message'):
                msg = msg + u'\n' + unicode(e.message)
        except socket.timeout:
            err = True
            msg = _(u'The request timed out, host unreachable')
        except Exception:
            err = True
            e = sys.exc_info()[0]
            if hasattr(e, 'message'):
                msg = unicode(e.message, errors='ignore')
            msg = msg + u'\n' + unicode(traceback.format_exc(), errors='ignore')
        return err, msg


    def run(self):
        if self.taskKwargs['notify'] is True:
            notify(_('Task %s launching for event: %s') % (self.taskId, str(self.topic)))
        if isinstance(self.runtimeargs, list):
            if len(self.runtimeargs) > 0:
                self.runtimeargs = u''.join(self.runtimeargs)
            else:
                self.runtimeargs = u''
        s = requests.Session()
        url = self.taskKwargs['http']+self.runtimeargs
        if self.taskKwargs['user'] != '' and self.taskKwargs['pass'] != '':
            s.auth = (self.taskKwargs['user'], self.taskKwargs['pass'])
        if self.taskKwargs['request-type'] == 'POST-GET':
            verb = 'POST'
        else:
            verb = self.taskKwargs['request-type']

        err, msg = self.sendRequest(s, verb, url)

        if self.taskKwargs['request-type'] == 'POST-GET':
            err2, msg2 = self.sendRequest(s, 'GET', url, postget=True)
            err = err or err2
            msg = u'\n'.join([msg, msg2])

        s.close()
        self.threadReturn(err, msg)