# -*- coding: utf-8 -*-
##############################################################################
#
#    Odoo, Open Source Management Solution
#    Copyright (C) 2016-TODAY Prime Consulting SA, Cape Verde (<http://prime.cv>).
#
##############################################################################
import sys, os
from odoo import models, api
from datetime import datetime
import json
import urlparse
import logging
from bs4 import BeautifulSoup

_logger = logging.getLogger(__name__)


class ResUsers(models.Model):
    _inherit = "res.users"


    @api.model
    def custom_auth(self, data={}):
        print "DATA####################################################### ", data
        _logger.debug('DATA::::::::::::::::::::::::::::::::::::::::::::: %s',data)
        try:
            _logger.debug('TRY::::::::::::::::::::::::')
            if 'authorizationToken' in data:
                _logger.debug('IF authorizationToken::::::::::::::::::::::::')
                ebusiness = self.env['ecom.ebusiness'].search([('api_key', '=', data['authorizationToken'])], limit=1)

                if ebusiness:
                    _logger.debug('IF ebusiness::::::::::::::::::::::::')
                    enterprise = self.env['etourism.enterprise'].search([('ebusiness_id', '=', ebusiness.id)], limit=1)

                    if enterprise:
                        _logger.debug('IF enterprise::::::::::::::::::::::::')
                        code = 202
                        message = "Token authorized"
                        metadata = {
                            "id": enterprise.id,
                            "name": enterprise.name
                        }

                    else:
                        _logger.debug('ELSE enterprise::::::::::::::::::::::::')
                        code = 401
                        message = "No Enterprise registered for this authorization token"
                        metadata = {}

                else:
                    _logger.debug('ELSE EBUSINESS::::::::::::::::::::::::')
                    enterprises = self.env['etourism.enterprise'].search([('ebusiness_type_code', '=','AVT'),('ebusiness_id.active', '=',True)])

                    if enterprises:
                        _logger.debug('IF enterpriseS::::::::::::::::::::::::')
                        code = 202
                        message = "Token authorized"
                        metadata = {
                            "id": False,
                            "name": 'Portal'
                        }
                    else:
                        _logger.debug('ELSE enterpriseS::::::::::::::::::::::::')
                        code = 404
                        message = "No AVT Enterprise active"
                        metadata = {}
            else:
                _logger.debug('ELSE authorizationToken::::::::::::::::::::::::')
                code = 401
                message = "No authorization Token provided"
                metadata = {}

        except Exception as ex:
            print "EXCEPTION####################################################### "
            _logger.debug('Exception::::::::::::::::::::::::')
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3} "
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            code = 500
            metadata = {}

        return self.response_format(code, message, metadata)

    @api.model
    def custom_auth_avt(self, data={}):
        print "DATA####################################################### ", data
        _logger.debug('DATA::::::::::::::::::::::::::::::::::::::::::::: %s',data)
        try:
            print "TRY####################################################### "
            _logger.debug('TRY::::::::::::::::::::::::')
            if 'authorizationToken' in data:
                _logger.debug('IF authorizationToken::::::::::::::::::::::::')
                ebusiness = self.env['ecom.ebusiness'].search([('api_key', '=', data['authorizationToken'])], limit=1)

                if ebusiness:
                    _logger.debug('IF ebusiness::::::::::::::::::::::::')
                    enterprise = self.env['etourism.enterprise'].search([('ebusiness_id', '=', ebusiness.id)], limit=1)

                    if enterprise:
                        _logger.debug('IF enterprise::::::::::::::::::::::::')
                        code = 202
                        message = "Token authorized"
                        metadata = {
                            "id": enterprise.id,
                            "name": enterprise.name
                        }

                    else:
                        _logger.debug('ELSE enterprise::::::::::::::::::::::::')
                        code = 401
                        message = "No Enterprise registered for this authorization token"
                        metadata = {}

                else:
                    _logger.debug('ELSE EBUSINESS::::::::::::::::::::::::')
                    enterprises = self.env['etourism.enterprise'].search([('ebusiness_type_code', '=','AVT'),('ebusiness_id.active', '=',True)])

                    if enterprises:
                        _logger.debug('IF enterpriseS::::::::::::::::::::::::')
                        code = 202
                        message = "Token authorized"
                        metadata = {
                            "id": False,
                            "name": 'Portal'
                        }
                    else:
                        _logger.debug('ELSE enterpriseS::::::::::::::::::::::::')
                        code = 404
                        message = "No AVT Enterprise active"
                        metadata = {}
            else:
                _logger.debug('ELSE authorizationToken::::::::::::::::::::::::')
                code = 401
                message = "No authorization Token provided"
                metadata = {}

        except Exception as ex:
            print "EXCEPTION####################################################### "
            _logger.debug('Exception::::::::::::::::::::::::')
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3} "
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            code = 500
            metadata = {}

        return self.response_format(code, message, metadata)

    @api.model
    def tta_availability(self,  data={}):
        #print "DATA: ", data
        print "DATA TTA AVAILABILITY:::::::::::::::::::::::::::::::::::::::::::::::::::::: "
        _logger.debug('DATA TTA AVAILABILITY::::::::::::::::::::::::')
        result = []
        try:
            searchParams = {
                "enterprise_id": data['agencyId'],
                "date": data['date'],
                "num_pax": data['numPax']
            }
            if 'type' in data and data['type']:
                searchParams['type_code']=data['type']

            if 'package' in data and data['package']:
                searchParams['package']=data['package']

            if 'destination' in data and data['destination'] and data['destination']!=" ":
                searchParams['destination']=data['destination']

                _logger.debug('DATA TTA AVAILABILITY:::::::::::::::::::::::: %s'%(searchParams['destination']))

            date = datetime.strptime(searchParams['date'], "%Y/%m/%d").date()
            print "searchParams: ", searchParams
            _logger.debug('#1 ::::::::::::::::::::::::')
            #searchParams['enterprise_id']=str(searchParams['enterprise_id']).replace(",", "") if len(tuple(searchParams['enterprise_id'])) == 1 else searchParams['enterprise_id']
            enterprise_condition = "IN ({enterprise_id})".format(
                enterprise_id=searchParams['enterprise_id']
            ) if searchParams['enterprise_id'] else "IS NOT NULL"

            type_condition = "IN ('{type}')".format(
                type=searchParams['type_code']
            ) if 'type_code' in searchParams else "IS NOT NULL"

            package_condition = "IN ('{package}')".format(
                package=searchParams['package']

            ) if 'package' in searchParams else "IS NOT NULL"
            _logger.debug('#2 ::::::::::::::::::::::::')

            if 'destination' in searchParams and searchParams['destination'] and searchParams['destination']!=' ':
                #print "FIRST QUERY"
                _logger.debug('#3 ::::::::::::::::::::::::')
                self._cr.execute("""
                    select * from (select a.name,COALESCE(a.description,false::text) as description,COALESCE(a.description_en,false::text) as description_en
,COALESCE(a.terms_and_conditions,false::text) as terms_and_conditions,COALESCE(a.terms_and_conditions_en,false::text) as terms_and_conditions_en,
                        COALESCE(a.price,0) as price,
                        COALESCE(a.price_euros,0) as price_euros,
                        a.package_id,
                        COALESCE(a.schedule,false::text) as schedule,
						COALESCE(a.schedule_en,false::text) as schedule_en, 
                        a.item_id as itemId,
                        a.enterprise_id as agencyId,
                        a.enterprise_code as agencyCode,
                        COALESCE(a.book_before,0) as bookBefore,
                        a.min_quantity as minPax,
                        a.max_occupancy as maxPax,
                        a.duration,
                        a.type,
                        a.code,
                        a.type_code,
                        a.images_url,
                        a.image_url,
                        a.video_url,get_match_location(a.package_id,'{destination_condition}') as match
                        FROM package_view as a
                        WHERE a.enterprise_id {enterprise_condition}
                        AND a.type_code {type_condition}
                        AND a.code {package_condition}
                        AND a.start_date<='{date}'
                        AND a.end_date>='{date}'
                        AND a.max_occupancy>={num_pax}
                        AND a.min_quantity<={num_pax}
                        AND (
                        SELECT COUNT(*)
                        FROM   package_view b
                        WHERE  b.package_id = a.package_id
                        AND b.max_occupancy <= a.max_occupancy
                        AND b.enterprise_id {enterprise_condition}
                        AND a.type_code {type_condition}
                        AND a.code {package_condition}
                        AND b.start_date<='{date}'
                        AND b.end_date>='{date}'
                        AND b.max_occupancy>={num_pax}
                        AND b.min_quantity<={num_pax}
                         ) = 1
                        ) a WHERE a.match>=1
                """.format(
                    enterprise_condition=enterprise_condition,
                    destination_condition=searchParams['destination'],
                    type_condition=type_condition,
                    package_condition=package_condition,
                    date=date,
                    num_pax=searchParams['num_pax'])
                )
                query = """
                    select * from (select a.name,COALESCE(a.description,false::text) as description,COALESCE(a.description_en,false::text) as description_en
,COALESCE(a.terms_and_conditions,false::text) as terms_and_conditions,COALESCE(a.terms_and_conditions_en,false::text) as terms_and_conditions_en,
                        COALESCE(a.price,0) as price,
                        COALESCE(a.price_euros,0) as price_euros,
                        a.package_id,
                        COALESCE(a.schedule,false::text) as schedule,
						COALESCE(a.schedule_en,false::text) as schedule_en, 
                        a.item_id as itemId,
                        a.enterprise_id as agencyId,
                        a.enterprise_code as agencyCode,
                        COALESCE(a.book_before,0) as bookBefore,
                        a.min_quantity as minPax,
                        a.max_occupancy as maxPax,
                        a.duration,
                        a.type,
                        a.code,
                        a.type_code,
                        a.images_url,
                        a.image_url,
                        a.video_url,get_match_location(a.package_id,'{destination_condition}') as match
                        FROM package_view as a
                        WHERE a.enterprise_id {enterprise_condition}
                        AND a.type_code {type_condition}
                        AND a.code {package_condition}
                        AND a.start_date<='{date}'
                        AND a.end_date>='{date}'
                        AND a.max_occupancy>={num_pax}
                        AND a.min_quantity<={num_pax}
                        AND (
                        SELECT COUNT(*)
                        FROM   package_view b
                        WHERE  b.package_id = a.package_id
                        AND b.max_occupancy <= a.max_occupancy
                        AND b.enterprise_id {enterprise_condition}
                        AND a.type_code {type_condition}
                        AND a.code {package_condition}
                        AND b.start_date<='{date}'
                        AND b.end_date>='{date}'
                        AND b.max_occupancy>={num_pax}
                        AND b.min_quantity<={num_pax}
                         ) = 1
                        ) a WHERE a.match>=1
                """.format(
                    enterprise_condition=enterprise_condition,
                    destination_condition=searchParams['destination'],
                    type_condition=type_condition,
                    package_condition=package_condition,
                    date=date,
                    num_pax=searchParams['num_pax'])
                _logger.debug('QUERY1:::::::::::::::::::::::: %s'%(query))

            else:
                _logger.debug('#4 ::::::::::::::::::::::::')
                #print "SECOND QUERY"
                self._cr.execute("""
                                    SELECT 
                                        a.name,COALESCE(a.description,false::text) as description,COALESCE(a.description_en,false::text) as description_en
,COALESCE(a.terms_and_conditions,false::text) as terms_and_conditions,COALESCE(a.terms_and_conditions_en,false::text) as terms_and_conditions_en,
                                        COALESCE(a.price,0) as price,
                                        COALESCE(a.price_euros,0) as price_euros,
                                        a.package_id,
                                        COALESCE(a.schedule,false::text) as schedule,
										COALESCE(a.schedule_en,false::text) as schedule_en,
                                        a.item_id as itemId,
                                        a.enterprise_id as agencyId,
										a.enterprise_code as agencyCode,
                                        a.enterprise_name as agencyName,
                                        a.min_quantity as minPax,
                                        a.max_occupancy as maxPax,
                                        a.duration,
                                        a.type,
                                        a.code,
                                        a.type_code,
                                        a.images_url,
                                        a.image_url,
                                        a.video_url
                                    FROM package_view as a
                                    WHERE a.enterprise_id {enterprise_condition}
                                        AND a.type_code {type_condition}
                                        AND a.code {package_condition}
                                        AND a.start_date<='{date}'
                                        AND a.end_date>='{date}'
                                        AND a.max_occupancy>={num_pax}
                                        AND a.min_quantity<={num_pax}
                                        AND (
                                            SELECT COUNT(*)
                                            FROM   package_view b
                                            WHERE  b.package_id = a.package_id
                                                AND b.max_occupancy <= a.max_occupancy
                                                AND b.enterprise_id {enterprise_condition}
                                                AND a.type_code {type_condition}
                                                AND a.code {package_condition}
                                                AND b.start_date<='{date}'
                                                AND b.end_date>='{date}'
                                                AND b.max_occupancy>={num_pax}
                                                AND b.min_quantity<={num_pax}
                                             ) = 1
                                """.format(
                    enterprise_condition=enterprise_condition,
                    type_condition=type_condition,
                    package_condition=package_condition,
                    date=date,
                    num_pax=searchParams['num_pax'])
                )

            result = self._cr.dictfetchall()

            query = """
                                    SELECT 
                                        a.name,COALESCE(a.description,false::text) as description,COALESCE(a.description_en,false::text) as description_en
,COALESCE(a.terms_and_conditions,false::text) as terms_and_conditions,COALESCE(a.terms_and_conditions_en,false::text) as terms_and_conditions_en,
                                        COALESCE(a.price,0) as price,
                                        COALESCE(a.price_euros,0) as price_euros,
                                        a.package_id,
                                        COALESCE(a.schedule,false::text) as schedule,
										COALESCE(a.schedule_en,false::text) as schedule_en,
                                        a.item_id as itemId,
                                        a.enterprise_id as agencyId,
										a.enterprise_code as agencyCode,
                                        a.enterprise_name as agencyName,
                                        a.min_quantity as minPax,
                                        a.max_occupancy as maxPax,
                                        a.duration,
                                        a.type,
                                        a.code,
                                        a.type_code,
                                        a.images_url,
                                        a.image_url,
                                        a.video_url
                                    FROM package_view as a
                                    WHERE a.enterprise_id {enterprise_condition}
                                        AND a.type_code {type_condition}
                                        AND a.code {package_condition}
                                        AND a.start_date<='{date}'
                                        AND a.end_date>='{date}'
                                        AND a.max_occupancy>={num_pax}
                                        AND a.min_quantity<={num_pax}
                                        AND (
                                            SELECT COUNT(*)
                                            FROM   package_view b
                                            WHERE  b.package_id = a.package_id
                                                AND b.max_occupancy <= a.max_occupancy
                                                AND b.enterprise_id {enterprise_condition}
                                                AND a.type_code {type_condition}
                                                AND a.code {package_condition}
                                                AND b.start_date<='{date}'
                                                AND b.end_date>='{date}'
                                                AND b.max_occupancy>={num_pax}
                                                AND b.min_quantity<={num_pax}
                                             ) = 1
                                """.format(
                    enterprise_condition=enterprise_condition,
                    type_condition=type_condition,
                    package_condition=package_condition,
                    date=date,
                    num_pax=searchParams['num_pax'])
            _logger.debug('QUERY2:::::::::::::::::::::::: %s'%(query))

            _logger.debug('#5 ::::::::::::::::::::::::')

            if not result:
                code = 204
            else:
                #print "IS RESULT: ",len(result)
                _logger.debug('#6 ::::::::::::::::::::::::')
                for i,line in enumerate(result):
                    _logger.debug('#6.1 ::::::::::::::::::::::::')
                    #print "LINE: ",i
                    line['duration'] = eval(line.pop('duration'))
                    line['itemId'] = line.pop('itemid')
                    line['maxPax'] = line.pop('maxpax')
                    line['minPax'] = line.pop('minpax')
                    line['agencyId'] = line.pop('agencyid')
                    line['agencyCode'] = line.pop('agencycode')
                    line['logo_url'] = self.env['etourism.enterprise'].get_logo_url('etourism.enterprise', 'logo', line['agencyId'])
                    line['image_url'] = self.env['etourism.avt.package'].sudo().get_image_url('etourism.avt.package', 'image', line['package_id'])
                    line['images_url'] = line['images_url'] if line['images_url'] else False
                    if 'destination' in searchParams and searchParams['destination'] and searchParams['destination'] != ' ':
                        line.pop('match')

                    package_id = self.env['etourism.avt.package'].search([('id', '=', line['package_id'])], limit=1)
                    if package_id:
                        destinations = self.tta_destinations({'destinations_id':[location.id for location in package_id.locations]})
                        if 'code' in destinations and 'metadata' in destinations and int(destinations['code']) == 200 and destinations['metadata']:
                            line['location'] = destinations['metadata']['destinations']
                _logger.debug('#7 ::::::::::::::::::::::::')
                code = 200
            if not result:
                code = 204
            destinations = self.tta_destinations()
            agencies = self.tta_agencies()
            dest = []
            agenc = []
            _logger.debug('#8 ::::::::::::::::::::::::')
            if 'code' in destinations and 'metadata' in destinations and int(destinations['code'])==200 and destinations['metadata']:
                dest=destinations['metadata']['destinations']
                _logger.debug('#9 ::::::::::::::::::::::::')
            if 'code' in agencies and 'metadata' in agencies and int(agencies['code'])==200 and agencies['metadata']:
                _logger.debug('#10 ::::::::::::::::::::::::')
                agenc=agencies['metadata']['agencies']

            #print "RESULT: ", json.dumps(result)
            _logger.debug('RESULT:::::::::::::::::::::::: %s'%(json.dumps(result)))

            return self.response_format(code, metadata={"packages": result,'destinations':dest,'agencies':agenc})

        except Exception as ex:
            code=404
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3} "
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            #print message
            _logger.debug('#11 ::::::::::::::::::::::::')
            return self.response_format(code, message)

    @api.model
    def tta_book_request(self, data={}):
        print "REQUEST: ",data
        try:

            requestParams={
                "enterprise_id":data['agencyId'],
                "client":{
                    "name":data['client']['name'],
                    "phone":data['client']['phone'],
                    "email":data['client']['email'],
                    "origin_country":data['client']['origin_country']
                },
                "description": data['client']['description'],
                "date":data['date'],
                "num_pax":data['numPax']
            }

            customer = self.env['res.partner'].search([('email', '=', requestParams['client']['email'])], limit=1)
            if not customer:
                customer = self.env['res.partner'].create({
                    'name': requestParams['client']['name'],
                    'email': requestParams['client']['email'],
                    'phone': requestParams['client']['phone'],
                    'origin': requestParams['client']['origin_country'],
                })
            if customer:
                request = self.env['etourism.avt.booking.request'].create({
                    'enterprise_id': requestParams['enterprise_id'],
                    'date': requestParams['date'],
                    'num_pax': requestParams['num_pax'],
                    'description': requestParams['description'],
                    'client_id': customer.id
                })
                if request:
                    message = "Your exceptional request was successfully received."
                    metadata = {"bookingId": [request.request_no]}
                    code = 201
                else:
                    code = 404
                    message = "Was not possible to make a request, try again later"
                    metadata = {}
            else:
                code=404
                message = "Was not possible to make a request, without a costumer"
                metadata={}

        except Exception as ex:
            code=404
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3} "
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            metadata = {}

        return self.response_format(code, message,metadata)

    @api.model
    def tta_book(self, data={}):
        print "BOOKING DATA PRINT::::::::::::::::::::::::::::::::::::: ",data
        _logger.info("BOOKING DATA LOG:::::::::::::::::::::::::::::::::::::: %s." % (data))
        try:
            bookingParams={
                "enterprise_id":data['agencyId'],
                "items":data['items'],
                "client":{
                    "name":data['client']['name'],
                    "surname":data['client']['surname'],
                    "phone":data['client']['phone'],
                    "email":data['client']['email'],
                    "origin_country":data['client']['origin_country'],
                    "description": data['client']['description']
                },
                "date":data['date'],
                "num_pax":data['numPax']
            }

            if 'voucher' in data and data['voucher'] and data['voucher']!=' ':
                bookingParams['voucher'] = data['voucher']

            avail_packages = self.tta_availability({
                "numPax": bookingParams['num_pax'],
                "date": bookingParams['date'],
                "agencyId": bookingParams['enterprise_id']
            })['metadata']['packages']

            result_aval = {
                'packagesId': [item['package_id'] for item in avail_packages],
                'itemsId': [item['itemId'] for item in avail_packages],
                'agenciesId': [item['agencyId'] for item in avail_packages]
            }
            #print "RESULT: ",result_aval
            if any(t in result_aval['itemsId'] for t in bookingParams['items']):

                customer = self.env['res.partner'].search([('email', '=', bookingParams['client']['email'])], limit=1)
                if not customer:
                    customer = self.env['res.partner'].create({
                        'name': ' '.join([str(bookingParams['client']['name']), str(bookingParams['client']['surname'])]),
                        'email': bookingParams['client']['email'],
                        'phone': bookingParams['client']['phone'],
                        'origin': bookingParams['client']['origin_country']
                    })
                if customer:
                    booking_result=[]
                    customer.write({'phone':bookingParams['client']['phone'],'origin':bookingParams['client']['origin_country']})
                    for i,item in enumerate(bookingParams['items']):
                        if item in result_aval['itemsId']:
                            record = {
                                'enterprise_id': result_aval['agenciesId'][result_aval['itemsId'].index(item)],
                                'pricelist_item_id': item,
                                'package_id':result_aval['packagesId'][result_aval['itemsId'].index(item)],
                                'date':bookingParams['date'],
                                'num_pax':bookingParams['num_pax'],
                                'description':data['client']['description'],
                                'client_id':customer.id
                            }

                            if 'voucher' in bookingParams and bookingParams['voucher']:
                                pricelist_item = self.env['product.pricelist.item'].search(
                                    [('id', '=', item)], limit=1)
                                if pricelist_item:
                                    voucher = pricelist_item.validate_voucher(bookingParams['voucher'])
                                    voucher_valid = voucher.validate()
                                    #print "VOUCHER VALID: ", voucher_valid
                                    if voucher and voucher_valid['valid']:
                                        record['voucher_id'] = voucher.id
                            booking_record = self.env['etourism.avt.booking'].create(record)
                            if bookingParams['enterprise_id']:
                                entp = self.env['etourism.enterprise'].browse(bookingParams['enterprise_id'])
                                if entp.auto_confirm_bookings:
                                    booking_record.action_confirmed()
                            booking_result.append(booking_record)

                    #print " IDS: ", str([booking.reservation_no for booking in booking_result])
                    message = "Booking request was registered successfully."
                    metadata = {
                        "bookingId": [[booking.reservation_no, booking.token] for booking in booking_result],
                        "totalAmount": booking.total_amount
                    }
                    code = 201
                else:
                    code=404
                    message = "Was not possible to make a reservation, without a costumer"
                    metadata={}
            else:
                code = 404
                message = "Was not possible to make a reservation, the item selected is not available"
                metadata={}

            print " METADATA::::::::::::::::::::::::::::::::::::::::::::::::::::: ", metadata
            return self.response_format(code, message, metadata)

        except Exception as ex:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3}"
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            code=500
            if type(ex).__name__=="KeyError":
                code=400
            return self.response_format(code, message)

    @api.model
    def tta_pay(self, data={}):
        try:
            paymentParams = {
                "token": data['token'],
                "amount": data['amount'],
                "method": data['method']
            }
            #print "paymentParams: ", paymentParams
            bookingId = self.env['etourism.avt.booking'].search([('token', '=', paymentParams['token'])], limit=1)
            #print 'bookingId: ',bookingId
            if bookingId:
                if bookingId.state=='confirmed':
                    if float(bookingId.total_amount) != float(paymentParams['amount']):
                        code = 406
                        message = "Was not possible to register the payment, the amount paid does not match the reservation amount"
                        metadata = {
                            'paidAmount':paymentParams['amount'],
                            'total_amount': bookingId.total_amount
                        }
                    else:
                        sale_order_line = (0, 0, {
                            'product_id': bookingId.package_id.product_id.id,
                            'product_uom_qty': bookingId.num_pax,
                            'price_unit': bookingId.unitary_amount,
                            'name': bookingId.package_id.name,
                        })

                        sale_order_id = self.env['sale.order'].create({
                            'partner_id': bookingId.client_id.id,
                            'avt_booking_id': bookingId.id,
                            'pricelist_id':bookingId.pricelist_item_id.pricelist_id.id,
                            'order_line': [sale_order_line]
                        })
                        if sale_order_id:
                            sale_order_id.action_confirm()
                            invoices = sale_order_id.with_context(active_model='sale.order', enterprise_id=bookingId.package_id.enterprise_id.id, active_id=sale_order_id.id, company_id=sale_order_id.company_id.id).action_invoice_create()
                            invoices = [self.env['account.invoice'].browse([invoices[0]])]
                            _logger.info("Invoice has been created for Sales Order %s." % (sale_order_id.name))
                            if invoices:
                                company_id, single_inv = False, True
                                for inv in invoices:
                                    if single_inv:
                                        company_id = inv.company_id.id
                                        single_inv = False

                                journal_id = False
                                if paymentParams['method'] == 'creditCard':
                                    journal_id = self.env['ir.model.data'].xmlid_to_res_id('etourism_avt.account_journal_creditcard')
                                elif paymentParams['method'] == 'eCard':
                                    journal_id = self.env['ir.model.data'].xmlid_to_res_id('etourism_avt.account_journal_ecard')
                                elif paymentParams['method'] == 'cash':
                                    journal_id = self.env['account.journal'].search([('company_id', '=', company_id), ('type', '=', 'cash')])
                                    journal_id = journal_id and journal_id[0].id or False

                                if journal_id:
                                    self._register_payment(invoices, journal_id, bookingId.total_amount,bookingId.package_id.enterprise_id.id)
                                    message = "Payment Registered successfully for Invoice(s) against Sales Order %s." % (sale_order_id.name.upper())
                                    code = 202
                                    metadata = {
                                        'saleOrder':sale_order_id.name.upper()
                                    }
                                    bookingId.action_pay()
                                else:
                                    code = 500
                                    message = "Unable to register payment. Journal ID not found."
                                    metadata = {}
                elif bookingId.state == 'paid':
                    code = 406
                    message = "Payment already registered"
                    metadata = {
                        'paidAmount': paymentParams['amount'],
                        'total_amount': bookingId.total_amount
                    }
                else :
                    code = 406
                    message = "Was not possible to register the payment, the reservation must be in the confirmed state"
                    metadata = {
                        'paidAmount': paymentParams['amount'],
                        'total_amount': bookingId.total_amount
                    }
            else:
                code = 404
                message = "Was not possible to register the payment, the reservation does not exist"
                metadata = {}


        except Exception as ex:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3}"
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            code = 500
            metadata = {}
            if type(ex).__name__ == "KeyError":
                code = 400
        return self.response_format(code, message, metadata)

    def _register_payment(self, invoices, journal_id, amount,enterprise_id):
        def compute_payment_data(amount):
            vals = {}

            method_id = self.env['account.payment.method'].search([('payment_type', '=', 'inbound')], limit=1)
            vals['payment_method_id'] = method_id and method_id.id or False
            vals['journal_id'] = journal_id
            vals['amount'] = amount
            return vals

        def register_payment(invoice):
            vals = compute_payment_data(amount)
            vals['enterprise_id'] = enterprise_id
            payment_id = self.env['account.payment'].with_context(default_invoice_ids=[(4, invoice.id, None)]).create(
                vals)
            payment_id.post()

        for invoice in invoices:
            if invoice.state in ('draft', 'proforma', 'proforma2'):
                invoice.with_context(partner_id=invoice.partner_id.id).action_invoice_open()
                _logger.info("Invoice with ID %s has been Validated." % (invoice.id))
                register_payment(invoice)
            elif invoice.state == 'open':
                _logger.info("Payment has been Registered for Invoice with ID %s Invoice Number %s." % (
                invoice.id, invoice.number))
                register_payment(invoice)
        return True

    @api.model
    def validate_voucher(self, data={}):
        _logger.info("API function: Validating Voucher Code.")
        response = dict()
        Voucher = None
        if data and isinstance(data, dict):
            try:
                voucher_code = data.get('voucher', '')
                pricelist_item = data.get('item', '')
                if voucher_code and pricelist_item:
                    pricelist_item = self.env['product.pricelist.item'].search([('id', '=', pricelist_item)], limit=1)

                    if pricelist_item:
                        Voucher = pricelist_item.validate_voucher(voucher_code)

                    if not pricelist_item or not Voucher:
                        response = self.response_format(code='404')
                        response['message'] = 'Voucher code is not valid.'
                    elif Voucher:
                        voucher_validation = Voucher.validate()
                        if voucher_validation['valid']:
                            response = self.response_format(code='200')
                            response['metadata'] = {'type': Voucher.type, 'value': Voucher.value,
                                                    'voucher': voucher_code, 'voucher_id': Voucher[0].id}
                            response['message'] = '{agency}, Your Voucher is valid.'.format(agency=Voucher.agency_id.name)
                        else:
                            response = self.response_format(code='404')
                            response['message'] = voucher_validation['message']
                    else:
                        response = self.response_format(code='404')
                        response['message'] = 'Voucher code is not valid.'

                else:
                    response = self.response_format(code='500')
                    response['message'] = 'Missing Voucher Code or Booking item'
            except Exception, e:
                response = self.response_format(code='500')
                response['message'] = str(e).replace('None', 'False')
        else:
            response = self.response_format(code='500')
            response['message'] = "Wrong Input Data. Please check input data."
        _logger.info(response['message'])
        _logger.info(type(response))
        _logger.info(response)

        return response

    @api.model
    def tta_agencies(self, data={}):
        code = 200
        _logger.debug('#15 ::::::::::::::::::::::::')
        try:
            self._cr.execute("""SELECT DISTINCT enterprise_id,enterprise_name,enterprise_code FROM package_view""")
            result = self._cr.dictfetchall()
            _logger.debug('#16 ::::::::::::::::::::::::')

            if not result:
                code = 204
                message = "No agencies Found"
                metadata = {}
                _logger.debug('#17 ::::::::::::::::::::::::')
            else:
                code = 200
                message = "Found Agencies"
                for line in result:
                    line['agencyId'] = line.pop('enterprise_id')
                    line['agencyName'] = line.pop('enterprise_name')
                    line['agencyCode'] = line.pop('enterprise_code')
                metadata = {"agencies": result}
                _logger.debug('#18 ::::::::::::::::::::::::')
        except Exception as ex:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3}"
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            code = 500
            metadata = {}
            _logger.debug('#19 ::::::::::::::::::::::::')
            if type(ex).__name__ == "KeyError":
                code = 400

        _logger.debug('#20 ::::::::::::::::::::::::')

        return self.response_format(code, message, metadata)
    @api.model
    def tta_destinations(self, data={}):
        #print "TTA DESTINATION DATA: ",data
        _logger.debug('#12 ::::::::::::::::::::::::')
        try:
            _logger.debug('#13 ::::::::::::::::::::::::')
            locations_id = []

            if 'destinations_id' in data and data['destinations_id']:
                locations_id = data['destinations_id']

            code = 200
            self._cr.execute("""SELECT DISTINCT rel.location_id FROM package_location_rel rel""")
            results = self._cr.dictfetchall()

            #print "RESULT: ", json.dumps(results)
            if not results:
                code = 204
            else:
                if not locations_id:
                    locations_id = [result['location_id'] for result in results]
                if locations_id:
                    locations = self.env['ecom.location'].search([('id', 'in', locations_id)])
                    locations_list = []
                    locations_parent_list = []
                    if locations:
                        for location in locations:
                            #print "LOCATION: ",location
                            local_name = [location.name]
                            if location.parent_id:
                                local_name.append(location.parent_id.name)
                            if location.parent_id.parent_id:
                                local_name.append(location.parent_id.parent_id.name)
                                print "local_name: ",local_name
                            local = {
                                'name':location.name,
                                'code':location.code,
                                'level':location.level,
                                'render':", ".join(local_name)
                            }
                            locations_list.append(local)

                            if location.parent_id and location.parent_id not in locations_parent_list:
                                locations_parent_list.append(location.parent_id)
                            if location.parent_id.parent_id and location.parent_id.parent_id not in locations_parent_list:
                                locations_parent_list.append(location.parent_id.parent_id)

                        if locations_parent_list:
                            for location in locations_parent_list:
                                local = {
                                    'name': location.name,
                                    'code': location.code,
                                    'level': location.level,
                                    'render': ", ".join(filter(None, [location.name, location.parent_id.name if location.parent_id.name else None, location.parent_id.parent_id.name if location.parent_id.parent_id.name else None]))
                                }
                                locations_list.append(local)

                    #oredered_location = sorted(locations_list, key=lambda k: k['level'])
                    oredered_location = self.multikeysort(locations_list,['level','name'])

            #print "oredered_location: ",oredered_location,code
            return self.response_format(code, "THIS IS A DEMO", {'destinations':oredered_location})

        except Exception as ex:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            template = "An exception of type '{0}' occurred. Argument: {1!s}. FileName: {2}. Line: {3}"
            message = template.format(type(ex).__name__, ex.args[0], fname, exc_tb.tb_lineno)
            code = 500
            if type(ex).__name__ == "KeyError":
                code = 400
            #print "EXCEPTION: ", code, message
            _logger.debug('#14 ::::::::::::::::::::::::')
            return self.response_format(code, message)

    def response_format(self,code,message="",metadata={}):
        http_response = self.env['http.status'].search_read([('code', '=', code)], fields=['code', 'type', 'description'])[0]
        return {
            "code":http_response['code'],
            "type":http_response['type'][1],
            "description":http_response['description'],
            "message":message,
            "metadata":metadata
        }

    def multikeysort(self, items, columns):
        from operator import itemgetter
        comparers = [((itemgetter(col[1:].strip()), -1) if col.startswith('-') else
                      (itemgetter(col.strip()), 1)) for col in columns]

        def comparer(left, right):
            for fn, mult in comparers:
                result = cmp(fn(left), fn(right))
                if result:
                    return mult * result
            else:
                return 0

        return sorted(items, cmp=comparer)
