# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Helpers for testing."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import email
from six.moves import urllib

from framework import emailfmt
from framework import framework_bizobj
from mrproto import user_pb2
from services import service_manager
from services import template_svc
from testing import fake
from tracker import tracker_constants

DEFAULT_HOST = '127.0.0.1'

MINIMAL_HEADER_LINES = [
    ('From', 'user@example.com'),
    ('To', 'proj@monorail.example.com'),
    ('Cc', 'ningerso@chromium.org'),
    ('Subject', 'Issue 123 in proj: broken link'),
]

# Add one more (long) line for In-Reply-To
HEADER_LINES = MINIMAL_HEADER_LINES + [
    ('In-Reply-To', '<0=969704940193871313=13442892928193434663='
     'proj@monorail.example.com>'),
]

AlertEmailHeader = emailfmt.AlertEmailHeader
ALERT_EMAIL_HEADER_LINES = HEADER_LINES + [
    (AlertEmailHeader.INCIDENT_ID, '1234567890123456789'),
    (AlertEmailHeader.OWNER, 'owner@example.com'),
    (AlertEmailHeader.CC, 'cc1@example.com,cc2@example.com'),
    (AlertEmailHeader.PRIORITY, '0'),
    (AlertEmailHeader.STATUS, 'Unconfirmed'),
    (AlertEmailHeader.COMPONENT, 'Component'),
    (AlertEmailHeader.TYPE, 'Bug'),
    (AlertEmailHeader.OS, 'Android,Windows'),
    (AlertEmailHeader.LABEL, ''),
]


# TODO(crbug/monorail/7238): this should be moved to framework_bizobj
# as this is no longer only used for testing.
def ObscuredEmail(address):
  (_username, _domain, _obs_username,
   obs_email) = framework_bizobj.ParseAndObscureAddress(address)
  return obs_email

def MakeMessage(header_list, body):
  """Convenience function to make an email.message.Message."""
  msg = email.message.Message()
  for key, value in header_list:
    msg[key] = value
  msg.set_payload(body)
  return msg


def MakeMonorailRequest(*args, **kwargs):
  """Get just the monorailrequest.MonorailRequest() from GetRequestObjects."""
  _request, mr = GetRequestObjects(*args, **kwargs)
  return mr


def GetRequestObjects(
    headers=None, path='/', params=None, user_info=None,
    project=None, method='GET', perms=None, services=None, hotlist=None):
  """Make fake request and MonorailRequest objects for testing.

  Host param will override the 'Host' header, and has a default value of
  '127.0.0.1'.

  Args:
    headers: Dict of HTTP header strings.
    path: Path part of the URL in the request.
    params: Dict of query-string parameters.
    user_info: Dict of user attributes to set on a MonorailRequest object.
        For example, "user_id: 5" causes self.auth.user_id=5.
    project: optional Project object for the current request.
    method: 'GET' or 'POST'.
    perms: PermissionSet to use for this request.
    services: Connections to backends.
    hotlist: optional Hotlist object for the current request

  Returns:
    A tuple of (http Request, monorailrequest.MonorailRequest()).
  """
  headers = headers or {}
  params = params or {}

  headers.setdefault('Host', DEFAULT_HOST)
  post_items=None
  if method == 'POST' and params:
    post_items = params

  if not services:
    services = service_manager.Services(
        project=fake.ProjectService(),
        user=fake.UserService(),
        usergroup=fake.UserGroupService(),
        features=fake.FeaturesService())
    services.project.TestAddProject('proj')
    services.features.TestAddHotlist('hotlist')

  request = RequestStub(path, headers=headers, values=post_items)
  mr = fake.MonorailRequest(
      services, user_info=user_info, project=project, perms=perms,
      params=params, hotlist=hotlist)
  mr.ParseRequest(
      request, services, do_user_lookups=False)
  mr.auth.user_pb = user_pb2.MakeUser(0)
  return request, mr


class RequestStub(object):
  """flask.Request stub object.

  This stub is a drop-in replacement for flask.Request that implements all
  fields used in MonorailRequest.ParseRequest(). Its constructor API is
  designed to mimic webapp2.Request.blank() for backwards compatibility with
  existing unit tests previously written for webapp2.
  """

  def __init__(self, path, headers=None, values=None):
    self.scheme = 'http'
    self.path = path
    self.headers = headers or {}
    # webapp2.Request.blank() overrides the host from the request headers.
    self.host = self.headers.get('Host', 'localhost:80')
    self.host_url = self.scheme + '://' + self.host + '/'
    self.url = self.scheme + '://' + self.host + path

    parsed_url = urllib.parse.urlsplit(self.url)
    self.base_url = self.host_url + parsed_url.path  # No query string.

    self.values = values or {}
    # webapp2.Request.blank() parses the query string from the path.
    query = urllib.parse.parse_qs(parsed_url.query, True)
    self.values.update({key: value[0] for key, value in query.items()})


class Blank(object):
  """Simple class that assigns all named args to attributes.

  Tip: supply a lambda to define a method.
  """

  def __init__(self, **kwargs):
    vars(self).update(kwargs)

  def __repr__(self):
    return '%s(%s)' % (self.__class__.__name__, str(vars(self)))

  def __eq__(self, other):
    if other is None:
      return False
    return vars(self) == vars(other)


def DefaultTemplateRows():
  return [(
    None,
    789,
    template_dict['name'],
    template_dict['content'],
    template_dict['summary'],
    template_dict.get('summary_must_be_edited'),
    None,
    template_dict['status'],
    template_dict.get('members_only', False),
    template_dict.get('owner_defaults_to_member', True),
    template_dict.get('component_required', False),
    ) for template_dict in tracker_constants.DEFAULT_TEMPLATES]


def DefaultTemplates():
  return [template_svc.UnpackTemplate(t) for t in DefaultTemplateRows()]
