# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.conf.urls import url
from django.conf import settings
from tastypie.resources import Resource
from tastypie.utils import trailing_slash
from core.models.request import Request
from api.utils.odoo_api import (
    normalize_name,
    check_name,
    randomize_port,
    create_folders,
    create_configuration,
    create_database,
    copy_database_seed,
    restore_database,
    remove_database_seed,
    create_odoo_container,
    apply_permissions,
    get_odoo_internal_ip,
    install_modules
)
from api.utils.git_api import get_odoo_modules_repos_names
from api.utils.docker_api import get_all_containers
from api.utils.jwt_token import get_user
from api.utils.jwt_authentication import JWTAuthentication
from api.utils.logger import (
    info,
    error,
    warning
)
from api.utils.email import send_email
from simplejson import JSONDecodeError
import simplejson as json

class OdooResource(Resource):
    class Meta:
        authentication = JWTAuthentication()

    '''
    '''
    def prepend_urls(self):
        return [
            url(r'^(?P<resource_name>%s)/create%s$' % (self._meta.resource_name, trailing_slash), self.wrap_view('odoo_create'), name='api_odoo_create'),
            url(r'^(?P<resource_name>%s)/install_modules%s$' % (self._meta.resource_name, trailing_slash), self.wrap_view('install_odoo_modules'), name='api_install_odoo_modules'),
        ]
    
    '''
    '''
    def odoo_create(self, request, **kwargs):
        info('odoo creation is requested')

        self.method_check(request, allowed='post')
        self.is_authenticated(request)

        authorization_header = request.META.get(settings.JWT_ACCEPT_HEADER)
        prefix_length = len(settings.JWT_PREFIX_HEADER)
        user = get_user(authorization_header[prefix_length + 1:])

        info('%s is authenticated' % user.username)

        name = None
        try:
            data = json.loads(request.body)
            name = data['name']
        except JSONDecodeError:
            name = None
            error('json decode error')
        except KeyError:
            name = None
            error('key error')

        r = Request.objects.create(name='Crear contenedor Odoo')
        r.user = user

        if not name:
            r.issue = 'name is required'
            r.status = 5
            r.save()

            error('name is required')

            return self.create_response(request, {
                'error_message': 'name is required'
            })
        info('%s: request is ok' % name)

        # 1. Check and get name
        name = normalize_name(name)
        name_exists = check_name(name)

        if name_exists:
            r.issue = '%s: name is already exists' % name
            r.status = 5
            r.save()

            error('%s: name is already exists' % name)

            return self.create_response(request, {
                'error_message': '%s: name is already exists' % name
            })
        info('%s: name is ok' % name)
        
        # 2. Get port
        port = randomize_port()
        info('%s: port is ok' % port)

        # 3. Folder structure create
        folders_created = create_folders(name)
        if not folders_created:
            r.issue = '%s: folders structure cannot be created' % name
            r.status = 5
            r.save()

            error('%s: folders structure cannot be created' % name)

            return self.create_response(request, {
                'error_message': '%s: folders structure cannot be created' % name
            })
        info('%s: folders is ok' % name)

        # 4. Configuration create
        conf_created = create_configuration(name)
        if not conf_created:
            r.issue = '%s: configuration cannot be created' % name
            r.status = 5
            r.save()

            error('%s: configuration cannot be created' % name)
            return self.create_response(request, {
                'error_message': '%s: configuration cannot be created' % name
            })
        info('%s: configuration is ok' % name)

        # 5. Database create
        db_created = create_database(name)

        if not db_created:
            r.issue = '%s: database cannot be created' % name
            r.status = 5
            r.save()

            error('%s: database cannot be created' % name)
            return self.create_response(request, {
                'error_message': '%s: database cannot be created' % name
            })
        info('%s: database is ok' % name)

        # 6. Copy a database backup
        seed_copied = copy_database_seed()

        if not seed_copied:
            r.issue = '%s: database seed cannot be copied' % name
            r.status = 5
            r.save()

            error('%s: database seed cannot be copied' % name)
            return self.create_response(request, {
                'error_message': '%s: database seed cannot be copied' % name
            })
        info('%s: database seed is ok' % name)
        
        # 7. Restore database schema 
        db_restored = restore_database(name)
        
        if not db_restored:
            r.issue = '%s: database cannot be restored' % name
            r.status = 5
            r.save()

            error('%s: database cannot be restored' % name)
            return self.create_response(request, {
                'error_message': '%s: database cannot be restored' % name
            })
        info('%s: database restore is ok' % name)

        # 8. Remove unused bakup file
        seed_removed = remove_database_seed()

        if not seed_removed:
            r.issue = '%s: seed cannot be removed' % name
            r.status = 5
            r.save()

            error('%s: seed cannot be removed' % name)
            return self.create_response(request, {
                'error_message': '%s: seed cannot be removed' % name
            })
        info('%s: database seed remove is ok' % name)


        # 9. Odoo create
        odoo_created = create_odoo_container(name, [port])

        if not odoo_created:
            r.issue = '%s: odoo container cannot be created' % name
            r.status = 5
            r.save()

            error('%s: odoo container cannot be created' % name)
            return self.create_response(request, {
                'error_message': '%s: odoo container cannot be created' % name
            })
        info('%s: container creation is ok' % name)

        # 10. Apply permissions 
        permissions_applied = apply_permissions(name)

        if not permissions_applied:
            r.issue = '%s: odoo container cannot be started' % name
            r.status = 5
            r.save()

            error('%s: odoo container cannot be started' % name)
            return self.create_response(request, {
                'error_message': '%s: odoo container cannot be started' % name
            })
        info('%s: container started is ok' % name)

        r.issue = '%s: odoo container created successfully' % name
        r.status = 4
        r.save()

        # 11. Get internal IP
        internal_ip = get_odoo_internal_ip(name)

        # 12. Send email
        email_sended = send_email(
            '''
                El usuario %s ha creado exitosamente un nuevo sistema Odoo\n\n
                ------------------- Datos -------------------\n
                -\tNombre del Sistema:\t%s\n
                -\tIP Externo:\t%s\n
                -\tPuerto Externo:\t%s\n
                -\tIP Interno:\t%s\n
                ---------------------------------------------\n\n
                Obs.: Estos datos pueden ser usados para generar el subdominio del sistema
            ''' % (user.username, name, settings.EXTERNAL_IP, port, internal_ip),
            user.username,
            to_admins=True
        )

        if not email_sended:
            warning('%s email not sended' % user.username)
        else:
            info('%s email sended' % user.username)
        
        # 13. Send response
        info('%s: odoo creation is ok' % name)
        return self.create_response(request, {
            'action': {
                'type': 'redirect',
                'ip': settings.EXTERNAL_IP,
                'port': port
            }
        })

    '''
    '''
    def install_odoo_modules(self, request, **kwargs):
        info('odoo module installation is requested')

        self.method_check(request, allowed=['get', 'post'])
        self.is_authenticated(request)

        authorization_header = request.META.get(settings.JWT_ACCEPT_HEADER)
        prefix_length = len(settings.JWT_PREFIX_HEADER)
        user = get_user(authorization_header[prefix_length + 1:])

        info('%s is authenticated' % user.username)

        if request.META.get('REQUEST_METHOD') == 'GET':
            return self.create_response(request, {
                'containers': get_all_containers(),
                'repositories': get_odoo_modules_repos_names()
            })
        
        err = {'error_message': None}
        data = None

        try:
            data = json.loads(request.body)
        except JSONDecodeError:
            error('json decode error')

        r = Request.objects.create(name='Copiar/actualizar módulos de Odoo')
        r.user = user

        if not data:
            err['error_message'] = 'cannot parse request body'

        if data and (not 'system' in data or not 'modules' in data):
            err['error_message'] = 'module names and system name is required'

        system = data.get('system', '')
        modules = data.get('modules', [])

        result = install_modules(system, modules)

        if 'error' in result:
            err['error_message'] = result['error']

        if err['error_message']:    
            return self.create_response(request, err)

        module_names = ''
        for module_name in data.get('modules', []):
            module_names = '-\t' + module_name + '\n'

        r.issue = '%s: modules successfully installed' % system
        r.status = 4
        r.save()

        email_sended = send_email('El usuario %s ha instalado los siguientes módulos en el sistema %s:\n%s' % (user.username, system, module_names), user.username, only_admins=True)
         
        if not email_sended:
            warning('%s email not sended' % user.username)
        else:
            info('%s email sended' % user.username)
            
        return self.create_response(request, {
            'success_message': 'modules successfully installed'
        })
