import logging
import os
import json

from flask import Flask
from flask.ext.principal import Principal
from flask.ext.login import LoginManager
from flask.ext.mail import Mail

import features

from storage import Storage
from data import model
from data import database
from data.userfiles import Userfiles
from data.users import UserAuthentication
from util.analytics import Analytics
from util.exceptionlog import Sentry
from util.queuemetrics import QueueMetrics
from data.billing import Billing
from data.buildlogs import BuildLogs
from data.queue import WorkQueue
from data.userevent import UserEventsBuilderModule
from license import load_license
from datetime import datetime


OVERRIDE_CONFIG_FILENAME = 'conf/stack/config.py'
OVERRIDE_CONFIG_KEY = 'QUAY_OVERRIDE_CONFIG'
LICENSE_FILENAME = 'conf/stack/license.enc'


app = Flask(__name__)
logger = logging.getLogger(__name__)


if 'TEST' in os.environ:
  from test.testconfig import TestConfig
  logger.debug('Loading test config.')
  app.config.from_object(TestConfig())
else:
  from config import DefaultConfig
  logger.debug('Loading default config.')
  app.config.from_object(DefaultConfig())

  if os.path.exists(OVERRIDE_CONFIG_FILENAME):
    logger.debug('Applying config file: %s', OVERRIDE_CONFIG_FILENAME)
    app.config.from_pyfile(OVERRIDE_CONFIG_FILENAME)

  environ_config = json.loads(os.environ.get(OVERRIDE_CONFIG_KEY, '{}'))
  app.config.update(environ_config)

  logger.debug('Applying license config from: %s', LICENSE_FILENAME)
  try:
    app.config.update(load_license(LICENSE_FILENAME))
  except IOError:
    raise RuntimeError('No license file found, please check your configuration')

  if app.config.get('LICENSE_EXPIRATION', datetime.min) < datetime.utcnow():
    raise RuntimeError('License has expired, please contact support@quay.io')

features.import_features(app.config)

Principal(app, use_sessions=False)

login_manager = LoginManager(app)
mail = Mail(app)
storage = Storage(app)
userfiles = Userfiles(app)
analytics = Analytics(app)
billing = Billing(app)
sentry = Sentry(app)
build_logs = BuildLogs(app)
queue_metrics = QueueMetrics(app)
authentication = UserAuthentication(app)
userevents = UserEventsBuilderModule(app)

tf = app.config['DB_TRANSACTION_FACTORY']
image_diff_queue = WorkQueue(app.config['DIFFS_QUEUE_NAME'], tf)
dockerfile_build_queue = WorkQueue(app.config['DOCKERFILE_BUILD_QUEUE_NAME'], tf,
                                   reporter=queue_metrics.report)
notification_queue = WorkQueue(app.config['NOTIFICATION_QUEUE_NAME'], tf)

# TODO: Remove this in the prod push following the notifications change.
webhook_queue = WorkQueue(app.config['WEBHOOK_QUEUE_NAME'], tf)

database.configure(app.config)
model.config.app_config = app.config
model.config.store = storage

def get_app_url():
  return '%s://%s' % (app.config['PREFERRED_URL_SCHEME'], app.config['SERVER_HOSTNAME'])