import logging
import json

from app import analytics
from flask import request, abort as flask_abort, make_response, current_app
from auth.auth_context import get_authenticated_user, get_validated_token

logger = logging.getLogger(__name__)


DEFAULT_MESSAGE = {}
DEFAULT_MESSAGE[400] = 'Invalid Request'
DEFAULT_MESSAGE[401] = 'Unauthorized'
DEFAULT_MESSAGE[403] = 'Permission Denied'
DEFAULT_MESSAGE[404] = 'Not Found'
DEFAULT_MESSAGE[409] = 'Conflict'
DEFAULT_MESSAGE[501] = 'Not Implemented'


def _abort(status_code, data_object, headers):
  # Add CORS headers to all errors
  options_resp = current_app.make_default_options_response()
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = options_resp.headers['allow']
  headers['Access-Control-Max-Age'] = str(21600)
  headers['Access-Control-Allow-Headers'] = ['Authorization', 'Content-Type']

  resp = make_response(json.dumps(data_object), status_code, headers)

  # Report the abort to the user.
  flask_abort(resp)

def exact_abort(status_code, message=None):
  data = {}

  if message is not None:
    data['error'] = message

  _abort(status_code, data, {})

def abort(status_code, message=None, issue=None, headers=None, **kwargs):

  message = (str(message) % kwargs if message else
             DEFAULT_MESSAGE.get(status_code, ''))

  params = dict(request.view_args)
  params.update(kwargs)

  params['url'] = request.url
  params['status_code'] = status_code
  params['message'] = message

  # Add the user information.
  auth_user = get_authenticated_user()
  auth_token = get_validated_token()
  if auth_user:
    analytics.track(auth_user.username, 'http_error', params)
    message = '%s (user: %s)' % (message, auth_user.username)
  elif auth_token:
    analytics.track(auth_token.code, 'http_error', params)
    message = '%s (token: %s)' % (message,
                                  auth_token.friendly_name or auth_token.code)

  # Log the abort.
  logger.error('Error %s: %s; Arguments: %s' % (status_code, message, params))

  # Calculate the issue URL (if the issue ID was supplied).
  issue_url = None
  if issue:
    issue_url = 'http://docs.quay.io/issues/%s.html' % (issue)

  # Create the final response data and message.
  data = {}
  data['error'] = message

  if issue_url:
    data['info_url'] = issue_url

  if headers is None:
    headers = {}

  _abort(status_code, data, headers)
