# 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_formatted()
  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


