#!/usr/bin/env python
# -*- coding: utf-8 -*-
from datetime import datetime
import json
import logging
import time
import sys
import os
import os.path

import jsonpickle
import jsonpickle.backend
import tornado.web
from tornado import websocket
from tornado.httpclient import HTTPError

import config
from models import userConstant
from storage.mysql.database import session_manage
from storage.mysql.models import AdminUser, AdminOperationLog
from utils import util


class JsonBaseHandler(object):
    def build_json(self, data):
        """

        :rtype : object
        """
        backend = jsonpickle.backend.JSONBackend()
        backend.set_encoder_options("json", default=util.dthandler,
                                    ensure_ascii=False)
        return jsonpickle.encode(data, unpicklable=False, backend=backend)

    def build_success_json(self, data={}, info="", code=""):
        backend = jsonpickle.backend.JSONBackend()
        backend.set_encoder_options("json", default=util.dthandler,
                                    ensure_ascii=False)
        result = {'ret': 0, 'code': code, 'info': info}
        result.update(data)
        return jsonpickle.encode(result,
                                 unpicklable=False,
                                 backend=backend)

    def build_error_json(self, data={}, info="", code=""):
        backend = jsonpickle.backend.JSONBackend()
        backend.set_encoder_options("json", default=util.dthandler,
                                    ensure_ascii=False)
        result = {'ret': 1, 'code': code, 'info': info}
        result.update(data)
        return jsonpickle.encode(result,
                                 unpicklable=False,
                                 backend=backend)


class BaseHandler(tornado.web.RequestHandler, JsonBaseHandler):
    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__(application, request, **kwargs)
        super(JsonBaseHandler, self).__init__()
        self.per_page_num = config.app.layout.get("items_per_page")
        self.session = None
        self.log_message = ""

    def initialize(self):
        pass

    def json(self, data):
        """

        :rtype : object
        """
        self.set_header('Content-Type', 'application/json; charset=UTF-8')
        self.write(self.build_json(data))

    def send_success_json(self, data={}, info="", code=""):
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(self.build_success_json(data, info, code))

    def send_error_json(self, data={}, info="", code=""):
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(self.build_error_json(data, info, code))

    def handle_http_arguments(self, arguments):
        if not isinstance(arguments, dict):
            return
        for key, val in arguments.items():
            try:
                arguments[key] = val[0].strip()
            except:
                arguments[key] = val[0]
        return arguments

    @session_manage
    def get_current_user(self):
        user_id = self.get_secure_cookie("r_u_a")
        expire_time = self.get_secure_cookie("r_u_a_e")

        # user = AdminUser(id=12, username="daixuefeng", role="admin",)
        user = None
        if not user_id:
            return user

        now = time.time()
        idel = int(config.app.max_idle_time)
        try:
            expire = float(expire_time)
        except Exception:
            return user
        if expire < now:
            return user

        user = self.session.query(AdminUser).get(int(user_id))
        if not user or not user.state:
            return user

        expire_time = now + idel
        self.set_secure_cookie("u_a_e", u'{}'.format(expire_time))

        self.session.expunge(user)
        return user

    def get(self):
        path = self.get_argument("path")

        return self.render('login.html')

    @session_manage
    def record_log(self, content="", memo="", **kwargs):
        log = AdminOperationLog(content=content,
                                memo=memo,
                                create_time=datetime.now(),
                                ip=self.request.remote_ip)
        if self.current_user:
            current_user = self.session.query(AdminUser).get(
                self.current_user.id)
            log.admin_user = current_user
            # current_user.logs.append(log)
        else:
            self.session.add(log)

    def is_admin(self):
        return self.current_user.role == userConstant.USER_ROLE_ADMIN

    def render_raw_html(self, name):
        """Generate the given template with the given arguments.

        We return the generated byte string (in utf8). To generate and
        write a template as a response, use render() above.
        """
        # If no template_path is specified, use the path of the calling file
        template_path = self.get_template_path()
        if not template_path:
            frame = sys._getframe(0)
            web_file = frame.f_code.co_filename
            while frame.f_code.co_filename == web_file:
                frame = frame.f_back
            template_path = os.path.dirname(frame.f_code.co_filename)

        path = os.path.join(template_path, name)
        with open(path, "rb") as f:
            self.write(f.read())

    def asyn_response(self, reps):
        if isinstance(reps, HTTPError):
            self.send_error_json(info=reps.message, code=reps.code)
        else:
            self.send_success_json(json.loads(reps.body))


class BaseWebSocketHandler(websocket.WebSocketHandler, JsonBaseHandler):
    def __init__(self, application, request, **kwargs):
        super(BaseWebSocketHandler, self).__init__(application, request,
                                                   **kwargs)
        super(JsonBaseHandler, self).__init__()

    def json(self, data):
        self.write(self.build_json(data))

    def send_success_json(self, data={}, info="", code=""):
        self.write(self.build_success_json(data, info, code))

    def send_error_json(self, data={}, info="", code=""):
        self.write(self.build_error_json(data, info, code))


class DefaultHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        logging.info(
            "revere index url : %s" % "index.html")
        self.redirect("/report_common")


class GetTemplateHandler(BaseHandler):
    def get(self):
        page = self.get_argument("page")
        self.render_raw_html(page)


class GetRawTemplateHandler(BaseHandler):
    def get(self, path):
        self.render_raw_html(path)