from flask import Flask, g, render_template, request
from flask.json import JSONEncoder
from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_wtf.csrf import CSRFProtect, CSRFError
from flask_babel import Babel, lazy_gettext
from flask_moment import Moment

from werkzeug.contrib.fixers import ProxyFix
from config import config

app = Flask(__name__)
app.config.from_object(config['default'])
config['default'].init_app(app)
app.wsgi_app = ProxyFix(app.wsgi_app)

db = SQLAlchemy(session_options = { "autoflush": False })
db.init_app(app)
lm = LoginManager()
lm.init_app(app)
lm.login_view = 'auth.login'
lm.login_message = 'Login Required.'
lm.session_protection = 'strong'
#lm.session_protection = 'basic'
mail = Mail()
mail.init_app(app)
bootstrap = Bootstrap()
bootstrap.init_app(app)
csrf = CSRFProtect(app)
#csrf.init_app(app)
babel = Babel()
babel.init_app(app)
moment = Moment(app)
moment.init_app(app)

from .main import main as main_blueprint
app.register_blueprint(main_blueprint)

from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')

from .news import news as news_blueprint
app.register_blueprint(news_blueprint, url_prefix='/news')

from .admin import admin as admin_blueprint
app.register_blueprint(admin_blueprint, url_prefix='/' + app.config['ADMIN_PREFIX'])

from .settings import settings as settings_blueprint
app.register_blueprint(settings_blueprint, url_prefix='/settings')

from .vmanager import vmanager as vmanager_blueprint
app.register_blueprint(vmanager_blueprint, url_prefix='/vmanager')

from .smanager import smanager as smanager_blueprint
app.register_blueprint(smanager_blueprint, url_prefix='/smanager')

from .dmanager import dmanager as dmanager_blueprint
app.register_blueprint(dmanager_blueprint, url_prefix='/dmanager')

from .uinvoice import uinvoice as uinvoice_blueprint
app.register_blueprint(uinvoice_blueprint, url_prefix='/uinvoice')

class CustomJSONEncoder(JSONEncoder):
    """This class adds support for lazy translation texts to Flask's
    JSON encoder. This is necessary when flashing translated texts."""
    def default(self, obj):
        from speaklater import is_lazy_string
        if is_lazy_string(obj):
            try:
                return unicode(obj)  # python 2
            except NameError:
                return str(obj)  # python 3
        return super(CustomJSONEncoder, self).default(obj)

app.json_encoder = CustomJSONEncoder

#TODO: if app.debug:
if not app.debug:
    import logging
    from logging.handlers import RotatingFileHandler
    file_handler = RotatingFileHandler('/home/proxadmin/appserver/proxadmin/log/proxadmin.log', 'a', 1 * 1024 * 1024, 10)
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
    app.logger.addHandler(file_handler)
    app.logger.setLevel(logging.DEBUG)
    #app.logger.info('Proxadmin started.')

@app.errorhandler(403)
def forbidden(e):
    if request.accept_mimetypes.accept_json and \
            not request.accept_mimetypes.accept_html:
        response = jsonify({'error': 'forbidden'})
        response.status_code = 403
        return response
    return render_template('errors/403.html'), 403

@app.errorhandler(404)
def page_not_found(e):
    if request.accept_mimetypes.accept_json and \
            not request.accept_mimetypes.accept_html:
        response = jsonify({'error': 'not found'})
        response.status_code = 404
        return response
    return render_template('errors/404.html'), 404

@app.errorhandler(500)
def internal_server_error(e):
    if request.accept_mimetypes.accept_json and \
            not request.accept_mimetypes.accept_html:
        response = jsonify({'error': 'internal server error'})
        response.status_code = 500
        return response
    return render_template('errors/500.html'), 500

@app.errorhandler(503)
def service_unavailable(e):
    if request.accept_mimetypes.accept_json and \
            not request.accept_mimetypes.accept_html:
        response = jsonify({'error': 'service unavailable'})
        response.status_code = 503
        return response
    return render_template('errors/503.html'), 503

@app.errorhandler(CSRFError)
def handle_csrf_error(e):
    return render_template('errors/csrf_error.html', reason=e.description), 400

@babel.localeselector
def get_locale():
    return request.accept_languages.best_match(app.config['SUPPORTED_LOCALES'])

#@app.before_request
#def before_request():
#    g.request_start_time = time.time()
#    g.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time)
#    g.pjax = 'X-PJAX' in request.headers

if not app.debug and app.config['MAIL_SERVER'] != '':
    import logging
    from logging.handlers import SMTPHandler
    credentials = None
    secure = None
    if app.config['MAIL_USERNAME'] or app.config['MAIL_PASSWORD']:
        credentials = (app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
        if app.config['MAIL_USE_TLS'] is None:
            secure = ()
    mail_handler = SMTPHandler(
        mailhost=(app.config['MAIL_SERVER'], app.config['MAIL_PORT']),
        fromaddr=app.config['MAIL_SENDER'],
        toaddrs=[app.config['MAIL_ADMIN']],
        subject=app.config['MAIL_SUBJECT_PREFIX'] + ' Application Error',
        credentials=credentials,
        secure=secure)
    mail_handler.setLevel(logging.ERROR)
    app.logger.addHandler(mail_handler)


if __name__ == '__main__':
    app.run()
