# Copyright 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

from google.appengine.ext import db
from google.appengine.api import mail
from google.appengine.api import users
from google.appengine.runtime import apiproxy_errors

import django.template

import email
import library
import models
from internal import util

def get_default_sender():
  return models.Settings.get_settings().from_email

def _encode_safely(s):
  """Helper to turn a unicode string into 8-bit bytes."""
  if isinstance(s, unicode):
    s = s.encode('utf-8')
  return s

def to_email_string(obj):
  if not obj:
    return None
  if isinstance(obj, str):
    return obj
  elif isinstance(obj, unicode):
    return obj.encode('utf-8')
  elif isinstance(obj, db.Email):
    account = models.Account.get_account_for_email(obj)
  elif isinstance(obj, users.User):
    account = models.Account.get_account_for_user(obj)
  elif isinstance(obj, models.Account):
    account = obj
  if account:
    result = account.get_email()
  else:
    result = str(email)
  return _encode_safely(result)

def make_to_strings(to):
  return [x for x in [to_email_string(e) for e in to] if x]


def send(sender, to, subject, template, template_args):
  """Sends an email based on a template.

  All email address parameters can be: strings, unicode, db.Email users.User
  or models.Account objects.

  Returns a Message object, suitable for keeping in the db.

  Args:
    sender:   The From address.  Null if it should be sent from the role acct.
    to:       An email address or a list of email address to be in the To field.
    subject:  The subject line.
    template: The name of the template file to use from the mail dir.
    template_args:  A map of args to be pasaed to the template
  """
  sender_string = to_email_string(sender)
  if not sender_string:
    return 'no from address'
  to_strings = make_to_strings(to)
  if not to_strings:
    return 'no to addresses'
  body = django.template.loader.render_to_string(template, template_args)
  try:
    mail.send_mail(sender=sender_string,
                   to=to_strings,
                   subject=subject,
                   body=body)
  except apiproxy_errors.OverQuotaError, e:
    logging.error(str(e), exc_info=True)

def make_change_subject(change):
  subject = "Change %s: (%s) %s" % (change.key().id(), change.dest_project.name,
                                    change.subject)
  if change.message_set.count(1) > 0:
    subject = 'Re: ' + subject
  return subject

def send_change_message(request,
                        change,
                        template,
                        template_args,
                        sender,
                        send_email=True,
                        email_template=None,
                        additional_to=[]):
  # sender
  default = get_default_sender()
  if not sender:
    sender = default
  sender_string = to_email_string(sender)

  # to
  to_users = set(  [change.owner]
                 + change.reviewers
                 + change.cc
                 + [default]
                 + additional_to)
  if sender in to_users:
    to_users.remove(sender)
  to_strings = make_to_strings(to_users)
  to_emails = [db.Email(s) for s in to_strings]

  # subject
  subject = make_change_subject(change)

  # body
  uri = library.change_url(change)
  if template_args is None:
    template_args = dict()
  else:
    template_args = dict(template_args)
  template_args['change'] = change

  if not email_template:
    email_template = template
  body = django.template.loader.render_to_string(email_template,
                                                 template_args)

  # don't send emails without all of these fields
  if not sender_string or not to_strings or not subject or not body:
    return None

  # send the email
  if send_email:
    message_body = "%s\n--\n%s\n" % (body, uri)
    try:
      mail.send_mail(sender=sender_string,
                     to=to_strings,
                     subject=subject,
                     body=message_body)
    except apiproxy_errors.OverQuotaError, e:
      logging.error(str(e), exc_info=True)
  
  # make and return the email
  if email_template != template:
    body = django.template.loader.render_to_string(
                                          template, template_args)
  msg = models.Message(change=change,
                       subject=util.u(subject),
                       sender=util.u(sender_string),
                       recipients=to_emails,
                       text=db.Text(body),
                       parent=change)
  return msg


