// Copyright (C) 2009 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.

package com.google.gerrit.server.mail;

import com.google.gerrit.common.data.ParamertizedString;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;

/** Creates a {@link FromAddressGenerator} from the {@link GerritServerConfig} */
@Singleton
public class FromAddressGeneratorProvider implements
    Provider<FromAddressGenerator> {
  private final FromAddressGenerator generator;

  @Inject
  FromAddressGeneratorProvider(@GerritServerConfig final Config cfg,
      @GerritPersonIdent final PersonIdent myIdent,
      final AccountCache accountCache) {

    final String from = cfg.getString("sendemail", null, "from");
    final Address srvAddr = toAddress(myIdent);

    if (from == null || "MIXED".equalsIgnoreCase(from)) {
      ParamertizedString name = new ParamertizedString("${user} (Code Review)");
      generator = new PatternGen(srvAddr, accountCache, name, srvAddr.email);

    } else if ("USER".equalsIgnoreCase(from)) {
      generator = new UserGen(accountCache, srvAddr);

    } else if ("SERVER".equalsIgnoreCase(from)) {
      generator = new ServerGen(srvAddr);

    } else {
      final Address a = Address.parse(from);
      final ParamertizedString name = new ParamertizedString(a.name);
      if (name.getParameterNames().isEmpty()) {
        generator = new ServerGen(a);
      } else {
        generator = new PatternGen(srvAddr, accountCache, name, a.email);
      }
    }
  }

  private static Address toAddress(final PersonIdent myIdent) {
    return new Address(myIdent.getName(), myIdent.getEmailAddress());
  }

  @Override
  public FromAddressGenerator get() {
    return generator;
  }

  static final class UserGen implements FromAddressGenerator {
    private final AccountCache accountCache;
    private final Address srvAddr;

    UserGen(AccountCache accountCache, Address srvAddr) {
      this.accountCache = accountCache;
      this.srvAddr = srvAddr;
    }

    @Override
    public boolean isGenericAddress(Account.Id fromId) {
      return false;
    }

    @Override
    public Address from(final Account.Id fromId) {
      if (fromId != null) {
        final Account a = accountCache.get(fromId).getAccount();
        if (a.getPreferredEmail() != null) {
          return new Address(a.getFullName(), a.getPreferredEmail());
        }
      }
      return srvAddr;
    }
  }

  static final class ServerGen implements FromAddressGenerator {
    private final Address srvAddr;

    ServerGen(Address srvAddr) {
      this.srvAddr = srvAddr;
    }

    @Override
    public boolean isGenericAddress(Account.Id fromId) {
      return true;
    }

    @Override
    public Address from(final Account.Id fromId) {
      return srvAddr;
    }
  }

  static final class PatternGen implements FromAddressGenerator {
    private final String senderEmail;
    private final Address serverAddress;
    private final AccountCache accountCache;
    private final ParamertizedString namePattern;

    PatternGen(final Address serverAddress, final AccountCache accountCache,
        final ParamertizedString namePattern, final String senderEmail) {
      this.senderEmail = senderEmail;
      this.serverAddress = serverAddress;
      this.accountCache = accountCache;
      this.namePattern = namePattern;
    }

    @Override
    public boolean isGenericAddress(Account.Id fromId) {
      return false;
    }

    @Override
    public Address from(final Account.Id fromId) {
      final String senderName;

      if (fromId != null) {
        final Account account = accountCache.get(fromId).getAccount();
        String fullName = account.getFullName();
        if (fullName == null || "".equals(fullName)) {
          fullName = "Anonymous Coward";
        }
        senderName = namePattern.replace("user", fullName).toString();

      } else {
        senderName = serverAddress.name;
      }

      return new Address(senderName, senderEmail);
    }
  }
}
