#!/usr/bin/env python
# -*- coding: utf-8 -*-
import bottle
import json
import xmltodict
from bottle import route, run, response
from CepTracker import CepTracker
import requests
from correios import Correios
from database import MongoDb as Database


app_v1 = bottle.Bottle()
jsonp_query_key = 'callback'


def expired(record_date):
    from datetime import datetime, timedelta

    # 6 months
    WEEKS = 26

    now = datetime.now()

    return (now - record_date['v_date'] >= timedelta(weeks=WEEKS))


def _get_info_from_source(cep):
    tracker = CepTracker()
    info = tracker.track(cep)
    if len(info) == 0:
        raise ValueError()
    return info


def format_result(result):
    # checa se foi solicitada resposta em JSONP
    js_func_name = bottle.request.query.get(jsonp_query_key)

    #checa se foi solicitado xml
    format = bottle.request.query.get('format')
    if format == 'xml':
        response.content_type = 'application/xml'
        return xmltodict.unparse({'result': result})

    if js_func_name:
        # se a resposta vai ser JSONP, o content type deve ser js e seu
        # conteudo deve ser JSON
        response.content_type = 'application/javascript'
        result = json.dumps(result)

        result = '%s(%s);' % (js_func_name, result)
    return result


@route('/cep/<cep:re:\d{5}-?\d{3}>')
@app_v1.route('/cep/<cep:re:\d{5}-?\d{3}>')
def verifica_cep(cep):
    cep = cep.replace('-', '')
    db = Database()
    response.headers['Access-Control-Allow-Origin'] = '*'

    result = db.get_one(cep, fields={'_id': False})
    if result and 'v_date' in result and not expired(result):
        result.pop('v_date')
    else:
        try:
            info = _get_info_from_source(cep)
        except ValueError:
            response.status = "404 O CEP {0} informado nao pode ser "
            "localizado".format(cep)
            return
        except requests.exceptions.RequestException:
            response.status = '503 Servico Temporariamente Indisponivel'
            return
        for item in info:
            db.insert_or_update(item)
        result = db.get_one(cep, fields={'_id': False, 'v_date': False})

    if result:
        response.headers['Cache-Control'] = 'public, max-age=2592000'
        return format_result(result)
    else:
        response.status = '404 O CEP %s informado nao pode ser '
        'localizado' % cep
        return

@app_v1.route('/uf/<sigla>')
def uf(sigla):
    sigla = sigla.lower()
    db = Database()
    result = db.get_one_uf(sigla, fields={'_id': False})
    if result:
        response.headers['Cache-Control'] = 'public, max-age=2592000'
        return format_result(result)
    else:
        response.status = '404 A sigla %s informada nao pode ser localizada'.format(sigla)
        return

@app_v1.route('/rastreio/<provider>/<track>')
def track_pack(provider, track):
    if provider == 'ect':
        try:
            encomenda = Correios.encomenda(track)

            resposta = dict()
            result = []

            for status in encomenda.status:
                historico = dict()
                historico['data'] = status.data
                historico['local'] = status.local
                historico['situacao'] = status.situacao
                historico['detalhes'] = status.detalhes

                result.append(historico)

            resposta['servico'] = provider
            resposta['codigo'] = track
            resposta['historico'] = result

            return format_result(resposta)

        except AttributeError:
            response.status = "404 O pacote {0} informado nao pode ser "
            "localizado".format(track)
    else:
        response.status = '404 O Servico %s nao pode ser encontrado' % provider

bottle.mount('/v1', app_v1)


def _standalone(port=9876):
    run(host='0.0.0.0', port=port)


if __name__ == "__main__":
    _standalone()