# -*- coding: utf-8 -*-
import logging
import os.path
import sys
import time

import redis
import tornado.escape
import tornado.ioloop
import tornado.options
import tornado.web
# import tornado.websocket
import torndb
import importlib
# from confluent_kafka import Producer
# from rediscluster import StrictRedisCluster
# from redis import sentinel
from rediscluster import RedisCluster
# from redis.sentinel import Sentinel
# from tornado.options import define, options
from tornado.options import options, define as _define, parse_command_line
# from elasticsearch import Elasticsearch
# from tornado_swagger import swagger



def define(name, default=None, type=None, help=None, metavar=None,
           multiple=False, group=None, callback=None):
    if name not in options._options:
        return _define(name, default, type, help, metavar,
                       multiple, group, callback)

tornado.options.define = define

sys.dont_write_bytecode = True

define("port", default=8888, help="run on the given port", type=int)
define("debug", default=0)

_ROOT = os.path.dirname(os.path.abspath(__file__))

importlib.reload(sys)
# sys.setdefaultencoding('utf-8')

try:
    import website
except ImportError:
    print("app package import error and try to config sys.path")
    logging.info("app import error")

    # sys.path.append(os.path.join(_ROOT, "../.."))
    sys.path.append(os.path.abspath(os.path.join(os.getcwd(), "..")))
    sys.path.append(os.path.abspath(os.path.join(os.getcwd(), "../..")))

from website import settings
from website.db_mysql import app_engine
from website.handler import APIErrorHandler
from website.urls import handlers, page_handlers
# from website.urls import handlers_v2
# print(os.path.dirname(os.path.abspath(__file__)))

class Connection(torndb.Connection):
    def __init__(self,
                 host,
                 database,
                 user=None,
                 password=None,
                 max_idle_time=7 * 3600,
                 connect_timeout=500,
                 time_zone="+0:00"):
        self.host = host
        self.database = database
        self.max_idle_time = float(max_idle_time)

        args = dict(conv=torndb.CONVERSIONS,
                    use_unicode=True,
                    charset="utf8",
                    db=database,
                    init_command=('SET time_zone = "%s";' %
                                  time_zone),
                    connect_timeout=connect_timeout,
                    sql_mode="TRADITIONAL")
        if user is not None:
            args["user"] = user
        if password is not None:
            args["passwd"] = password

        # We accept a path to a MySQL socket file or a host(:port) string
        if "/" in host:
            args["unix_socket"] = host
        else:
            self.socket = None
            pair = host.split(":")
            if len(pair) == 2:
                args["host"] = pair[0]
                args["port"] = int(pair[1])
            else:
                args["host"] = host
                args["port"] = 3306

        self._db = None
        self._db_args = args
        self._last_use_time = time.time()
        try:
            self.reconnect()
        except Exception:
            logging.error("Cannot connect to MySQL on %s",
                          self.host,
                          exc_info=True)


# class NoCacheStaticFileHandler(tornado.web.StaticFileHandler):
#     def set_extra_headers(self, path):
#         self.set_header("Cache-control", "no-cache")


class Application(tornado.web.Application):
    def __init__(self):
        # from website.handlers import Model
        handlers_ = []
        for handler in handlers:
            handlers_.append(("%s%s" % (settings.api_prefix, handler[0]),
                              handler[1]))

        for handler in page_handlers:
            handlers_.append((handler[0], handler[1]))

        # for handler in handlers_v2:
        #     handlers_.append(("%s%s" % (settings.api_prefix_v2, handler[0]),
        #                       handler[1]))

        # handlers_.append((r"/wap/s", tornado.web.RedirectHandler, dict(url=r"//wap/s.html")))
        handlers_.append((r".*", APIErrorHandler))
        # handlers_.append((r"/static/(.*)", NoCacheStaticFileHandler, {"path": os.path.join(_ROOT, "static")}))

        settings_ = dict(
            debug=options.debug,
            # login_url="/login",
            login_url="",
            cookie_secret=settings.cookie_secret,
            template_path=os.path.join(_ROOT, "templates"),
            static_path=os.path.join(_ROOT, "static"),
            xsrf_cookies=False,
            autoescape=None,
        )

        # self.db_app = Connection(
        #     settings.mysql_app["host"],
        #     settings.mysql_app["database"],
        #     user=settings.mysql_app["user"],
        #     password=settings.mysql_app["password"],
        #     time_zone=settings.mysql_app["time_zone"])

        self.app_mysql = app_engine

        # if settings.redis_sentinel == 1:
        #     rs = Sentinel(settings.redis_sentinel_nodes, socket_timeout=0.1)
        #     self.r_app = rs.master_for(settings.redis_sentinel_master,
        #                                socket_timeout=0.1,
        #                                password=settings.redis_sentinel_pwd)
        if settings.redis_cluster == 1:
            self.r_app = RedisCluster(startup_nodes=settings.redis_app_cluster_notes, decode_responses=True,
                                            password=settings.redis_cluster_pwd)
        else:
            self.r_app = redis.Redis(*settings.redis_app, decode_responses=True)
        # self.r_app = redis.Redis(*settings.redis_app)

        # self.kafka_producer = Producer(**settings.kafka_conf)
        # self.es = Elasticsearch(settings.es_nodes)

        # Model.setup_dbs({"db_app": self.db_app,
        #                  "r_app": self.r_app
        #                  })
        tornado.web.Application.__init__(self, handlers_, **settings_)
        # swagger.Application.__init__(self, handlers_, **settings_)


def sig_handler(signum, frame):
    tornado.ioloop.IOLoop.instance().stop()


class PwdFilter(logging.Filter):
    def filter(self, record):
        try:
            print("##########")
            print("{}, {}".format(record.name, record.msg))
        except Exception as e:
            print(e)
            pass
        return True


def main():
    tornado.options.parse_command_line()
    # options.parse_command_line()

    formatter = logging.Formatter(
        '[%(levelname)1.1s %(asctime)s.%(msecs)d '
        '%(module)s:%(funcName)s:%(lineno)d] %(message)s',
        "%Y-%m-%d %H:%M:%S"
    )  # creating own format
    for handler in logging.getLogger().handlers:  # setting format for all handlers
        handler.setFormatter(formatter)
        # handler.addFilter(PwdFilter())

    app = Application()
    # app.listen(options.port)

    server = tornado.httpserver.HTTPServer(app, max_buffer_size=104857600*3)
    server.listen(options.port)

    # def ping():
    #     try:
    #         row = app.db_app.get("select id from user limit 1")
    #         if row:
    #             logging.info("db check ok")
    #     except Exception as e:
    #         logging.info(e)
    #         logging.info("db connection err, reconnect")
    #         app.db_app.reconnect()

    logging.info("start app server...")

    # tornado.ioloop.PeriodicCallback(ping, 600000).start()
    tornado.ioloop.IOLoop.instance().start()


if __name__ == "__main__":
    main()