/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.eagle.notification.email;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.eagle.policy.common.Constants;
import org.apache.velocity.VelocityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.eagle.common.DateTimeUtil;
import org.apache.eagle.common.email.EagleMailClient;
import com.netflix.config.ConcurrentMapConfiguration;
import com.typesafe.config.ConfigObject;

public class AlertEmailSender implements Runnable {

    protected final List<Map<String, String>> alertContexts = new ArrayList<Map<String, String>>();
    protected final String configFileName;
    protected final String subject;
    protected final String sender;
    protected final String recipents;
    protected final String cc;
    protected final String origin;
    protected boolean sentSuccessfully = false;

    private final static Logger LOG = LoggerFactory.getLogger(AlertEmailSender.class);
    private final static int MAX_RETRY_COUNT = 3;

    private static final String MAIL_HOST = "mail.host";
    private static final String MAIL_PORT = "mail.smtp.port";
    private static final String MAIL_DEBUG = "mail.debug";

    private static final String CONF_KEY_MAIL_HOST = "mailHost";
    private static final String CONF_KEY_MAIL_PORT = "mailSmtpPort";
    private static final String CONF_KEY_MAIL_DEBUG = "mailDebug";

    private ConfigObject eagleProps;


    private String threadName;
    /**
     * Derived class may have some additional context properties to add
     * @param context velocity context
     * @param env environment
     */
    protected void additionalContext(VelocityContext context, String env) {
        // By default there's no additional context added
    }

    public AlertEmailSender(AlertEmailContext alertEmail){
        this.recipents = alertEmail.getRecipients();
        this.configFileName = alertEmail.getVelocityTplFile();
        this.subject = alertEmail.getSubject();
        this.sender = alertEmail.getSender();
        this.cc = alertEmail.getCc();
        for(AlertEmailComponent bean : alertEmail.getComponents()){
            this.alertContexts.add(bean.getAlertContext().getProperties());
        }
        String tmp = ManagementFactory.getRuntimeMXBean().getName();
        this.origin = tmp.split("@")[1] + "(pid:" + tmp.split("@")[0] + ")";
        threadName = Thread.currentThread().getName();
        LOG.info("Initialized "+threadName+": origin is : " + this.origin+", recipient of the email: " + this.recipents+", velocity TPL file: " + this.configFileName);
    }

    public AlertEmailSender(AlertEmailContext alertEmail, ConfigObject eagleProps){
        this(alertEmail);
        this.eagleProps = eagleProps;
    }

    @Override
    public void run() {
        int count = 0;
        boolean success = false;
        while(count++ < MAX_RETRY_COUNT && !success){
            LOG.info("Sending email, tried: " + count+", max: "+MAX_RETRY_COUNT);
            try {
                final EagleMailClient client;
                if (eagleProps != null) {
                    ConcurrentMapConfiguration con = new ConcurrentMapConfiguration();
                    con.addProperty(MAIL_HOST, eagleProps.get(CONF_KEY_MAIL_HOST).unwrapped());
                    con.addProperty(MAIL_PORT, eagleProps.get(CONF_KEY_MAIL_PORT).unwrapped());
                    if (eagleProps.get(CONF_KEY_MAIL_DEBUG) != null) {
                        con.addProperty(MAIL_DEBUG, eagleProps.get(CONF_KEY_MAIL_DEBUG).unwrapped());
                    }
                    client = new EagleMailClient(con);
                }
                else {
                    client = new EagleMailClient();
                }
                String env = "prod";
                if (eagleProps != null && eagleProps.get("env") != null) {
                    env = (String) eagleProps.get("env").unwrapped();
                }
                LOG.info("Env is: " + env);
                final VelocityContext context = new VelocityContext();
                generateCommonContext(context);
                LOG.info("After calling generateCommonContext...");
                additionalContext(context, env);

                if (recipents == null || recipents.equals("")) {
                    LOG.error("Recipients is null, skip sending emails ");
                    return;
                }
                String title = subject;
                if (!env.trim().equals("prod")) {
                    title = "[" + env + "]" + title;
                }
                success = client.send(sender, recipents, cc, title, configFileName, context, null);
                LOG.info("Success of sending email: " + success);
                if(!success && count < MAX_RETRY_COUNT) {
                    LOG.info("Sleep for a while before retrying");
                    Thread.sleep(10*1000);
                }
            }
            catch (Exception e){
                LOG.warn("Sending mail exception", e);
            }
        }

        if(success){
            sentSuccessfully = true;
            LOG.info(String.format("Successfully send email, thread: %s",threadName));
        }else{
            LOG.warn(String.format("Fail sending email after tries %s times, thread: %s",MAX_RETRY_COUNT,threadName));
        }
    }

    private void generateCommonContext(VelocityContext context) {
        context.put(Constants.ALERT_EMAIL_TIME_PROPERTY, DateTimeUtil.millisecondsToHumanDateWithSeconds( System.currentTimeMillis() ));
        context.put(Constants.ALERT_EMAIL_COUNT_PROPERTY, alertContexts.size());
        context.put(Constants.ALERT_EMAIL_ALERTLIST_PROPERTY, alertContexts);
        context.put(Constants.ALERT_EMAIL_ORIGIN_PROPERTY, origin);
    }

    public boolean sentSuccessfully(){
        return this.sentSuccessfully;
    }
}