/*
 * Copyright (c) 2016 Google Inc. All Rights Reserved.
 *
 * 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.android.vts.job;

import com.android.vts.entity.DeviceInfoEntity;
import com.android.vts.entity.TestAcknowledgmentEntity;
import com.android.vts.entity.TestCaseRunEntity;
import com.android.vts.entity.TestCaseRunEntity.TestCase;
import com.android.vts.entity.TestRunEntity;
import com.android.vts.entity.TestStatusEntity;
import com.android.vts.entity.TestStatusEntity.TestCaseReference;
import com.android.vts.proto.VtsReportMessage.TestCaseResult;
import com.android.vts.util.DatastoreHelper;
import com.android.vts.util.EmailHelper;
import com.android.vts.util.FilterUtil;
import com.android.vts.util.TimeUtil;
import com.google.appengine.api.datastore.DatastoreFailureException;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.DatastoreTimeoutException;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.SortDirection;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;

/** Represents the notifications service which is automatically called on a fixed schedule. */
public class VtsAlertJobServlet extends BaseJobServlet {
    private static final String ALERT_JOB_URL = "/task/vts_alert_job";
    protected static final Logger logger = Logger.getLogger(VtsAlertJobServlet.class.getName());
    protected static final int MAX_RUN_COUNT = 1000; // maximum number of runs to query for

    /**
     * Process the current test case failures for a test.
     *
     * @param status The TestStatusEntity object for the test.
     * @returns a map from test case name to the test case run ID for which the test case failed.
     */
    private static Map<String, TestCase> getCurrentFailures(TestStatusEntity status) {
        if (status.getFailingTestCases() == null || status.getFailingTestCases().size() == 0) {
            return new HashMap<>();
        }
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Map<String, TestCase> failingTestcases = new HashMap<>();
        Set<Key> gets = new HashSet<>();
        for (TestCaseReference testCaseRef : status.getFailingTestCases()) {
            gets.add(KeyFactory.createKey(TestCaseRunEntity.KIND, testCaseRef.parentId));
        }
        if (gets.size() == 0) {
            return failingTestcases;
        }
        Map<Key, Entity> testCaseMap = datastore.get(gets);

        for (TestCaseReference testCaseRef : status.getFailingTestCases()) {
            Key key = KeyFactory.createKey(TestCaseRunEntity.KIND, testCaseRef.parentId);
            if (!testCaseMap.containsKey(key)) {
                continue;
            }
            Entity testCaseRun = testCaseMap.get(key);
            TestCaseRunEntity testCaseRunEntity = TestCaseRunEntity.fromEntity(testCaseRun);
            if (testCaseRunEntity.testCases.size() <= testCaseRef.offset) {
                continue;
            }
            TestCase testCase = testCaseRunEntity.testCases.get(testCaseRef.offset);
            failingTestcases.put(testCase.name, testCase);
        }
        return failingTestcases;
    }

    /**
     * Get the test acknowledgments for a test key.
     *
     * @param testKey The key to the test whose acknowledgments to fetch.
     * @return A list of test acknowledgments.
     */
    private static List<TestAcknowledgmentEntity> getTestCaseAcknowledgments(Key testKey) {
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

        List<TestAcknowledgmentEntity> acks = new ArrayList<>();
        Filter testFilter =
                new Query.FilterPredicate(
                        TestAcknowledgmentEntity.TEST_KEY, Query.FilterOperator.EQUAL, testKey);
        Query q = new Query(TestAcknowledgmentEntity.KIND).setFilter(testFilter);

        for (Entity ackEntity : datastore.prepare(q).asIterable()) {
            TestAcknowledgmentEntity ack = TestAcknowledgmentEntity.fromEntity(ackEntity);
            if (ack == null) continue;
            acks.add(ack);
        }
        return acks;
    }

    /**
     * Get the test runs for the test in the specified time window.
     *
     * <p>If the start and end time delta is greater than one day, the query will be truncated.
     *
     * @param testKey The key to the test whose runs to query.
     * @param startTime The start time for the query.
     * @param endTime The end time for the query.
     * @return A list of test runs in the specified time window.
     */
    private static List<TestRunEntity> getTestRuns(Key testKey, long startTime, long endTime) {
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Filter testTypeFilter = FilterUtil.getTestTypeFilter(false, true, false);
        long delta = endTime - startTime;
        delta = Math.min(delta, TimeUnit.DAYS.toMicros(1));
        Filter runFilter =
                FilterUtil.getTimeFilter(
                        testKey, TestRunEntity.KIND, endTime - delta + 1, endTime, testTypeFilter);

        Query q =
                new Query(TestRunEntity.KIND)
                        .setAncestor(testKey)
                        .setFilter(runFilter)
                        .addSort(Entity.KEY_RESERVED_PROPERTY, SortDirection.DESCENDING);

        List<TestRunEntity> testRuns = new ArrayList<>();
        for (Entity testRunEntity :
                datastore.prepare(q).asIterable(FetchOptions.Builder.withLimit(MAX_RUN_COUNT))) {
            TestRunEntity testRun = TestRunEntity.fromEntity(testRunEntity);
            if (testRun == null) continue;
            testRuns.add(testRun);
        }
        return testRuns;
    }

    /**
     * Separate the test cases which are acknowledged by the provided acknowledgments.
     *
     * @param testCases The list of test case names.
     * @param devices The list of devices for a test run.
     * @param acks The list of acknowledgments for the test.
     * @return A list of acknowledged test case names that have been removed from the input test
     *     cases.
     */
    public static Set<String> separateAcknowledged(
            Set<String> testCases,
            List<DeviceInfoEntity> devices,
            List<TestAcknowledgmentEntity> acks) {
        Set<String> acknowledged = new HashSet<>();
        for (TestAcknowledgmentEntity ack : acks) {
            boolean allDevices = ack.getDevices() == null || ack.getDevices().size() == 0;
            boolean allBranches = ack.getBranches() == null || ack.getBranches().size() == 0;
            boolean isRelevant = allDevices && allBranches;

            // Determine if the acknowledgment is relevant to the devices.
            if (!isRelevant) {
                for (DeviceInfoEntity device : devices) {
                    boolean deviceAcknowledged =
                            allDevices || ack.getDevices().contains(device.getBuildFlavor());
                    boolean branchAcknowledged =
                            allBranches || ack.getBranches().contains(device.getBranch());
                    if (deviceAcknowledged && branchAcknowledged) isRelevant = true;
                }
            }

            if (isRelevant) {
                // Separate the test cases
                boolean allTestCases =
                        ack.getTestCaseNames() == null || ack.getTestCaseNames().size() == 0;
                if (allTestCases) {
                    acknowledged.addAll(testCases);
                    testCases.removeAll(acknowledged);
                } else {
                    for (String testCase : ack.getTestCaseNames()) {
                        if (testCases.contains(testCase)) {
                            acknowledged.add(testCase);
                            testCases.remove(testCase);
                        }
                    }
                }
            }
        }
        return acknowledged;
    }

    /**
     * Checks whether any new failures have occurred beginning since (and including) startTime.
     *
     * @param testRuns The list of test runs for which to update the status.
     * @param link The string URL linking to the test's status table.
     * @param failedTestCaseMap The map of test case names to TestCase for those failing in the last
     *     status update.
     * @param emailAddresses The list of email addresses to send notifications to.
     * @param messages The email Message queue.
     * @returns latest TestStatusMessage or null if no update is available.
     * @throws IOException
     */
    public TestStatusEntity getTestStatus(
            List<TestRunEntity> testRuns,
            String link,
            Map<String, TestCase> failedTestCaseMap,
            List<TestAcknowledgmentEntity> testAcks,
            List<String> emailAddresses,
            List<Message> messages)
            throws IOException {
        if (testRuns.size() == 0) return null;
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

        TestRunEntity mostRecentRun = null;
        Map<String, TestCaseResult> mostRecentTestCaseResults = new HashMap<>();
        Map<String, TestCase> testCaseBreakageMap = new HashMap<>();
        int passingTestcaseCount = 0;
        List<TestCaseReference> failingTestCases = new ArrayList<>();
        Set<String> fixedTestcases = new HashSet<>();
        Set<String> newTestcaseFailures = new HashSet<>();
        Set<String> continuedTestcaseFailures = new HashSet<>();
        Set<String> skippedTestcaseFailures = new HashSet<>();
        Set<String> transientTestcaseFailures = new HashSet<>();

        for (TestRunEntity testRun : testRuns) {
            if (mostRecentRun == null) {
                mostRecentRun = testRun;
            }
            List<Key> testCaseKeys = new ArrayList<>();
            for (long testCaseId : testRun.getTestCaseIds()) {
                testCaseKeys.add(KeyFactory.createKey(TestCaseRunEntity.KIND, testCaseId));
            }
            Map<Key, Entity> entityMap = datastore.get(testCaseKeys);
            for (Key testCaseKey : testCaseKeys) {
                if (!entityMap.containsKey(testCaseKey)) {
                    logger.log(Level.WARNING, "Test case entity missing: " + testCaseKey);
                    continue;
                }
                Entity testCaseRun = entityMap.get(testCaseKey);
                TestCaseRunEntity testCaseRunEntity = TestCaseRunEntity.fromEntity(testCaseRun);
                if (testCaseRunEntity == null) {
                    logger.log(Level.WARNING, "Invalid test case run: " + testCaseRun.getKey());
                    continue;
                }
                for (TestCase testCase : testCaseRunEntity.testCases) {
                    String testCaseName = testCase.name;
                    TestCaseResult result = TestCaseResult.valueOf(testCase.result);

                    if (mostRecentRun == testRun) {
                        mostRecentTestCaseResults.put(testCaseName, result);
                    } else {
                        if (!mostRecentTestCaseResults.containsKey(testCaseName)) {
                            // Deprecate notifications for tests that are not present on newer runs
                            continue;
                        }
                        TestCaseResult mostRecentRes = mostRecentTestCaseResults.get(testCaseName);
                        if (mostRecentRes == TestCaseResult.TEST_CASE_RESULT_SKIP) {
                            mostRecentTestCaseResults.put(testCaseName, result);
                        } else if (mostRecentRes == TestCaseResult.TEST_CASE_RESULT_PASS) {
                            // Test is passing now, witnessed a transient failure
                            if (result != TestCaseResult.TEST_CASE_RESULT_PASS
                                    && result != TestCaseResult.TEST_CASE_RESULT_SKIP) {
                                transientTestcaseFailures.add(testCaseName);
                            }
                        }
                    }

                    // Record test case breakages
                    if (result != TestCaseResult.TEST_CASE_RESULT_PASS
                            && result != TestCaseResult.TEST_CASE_RESULT_SKIP) {
                        testCaseBreakageMap.put(testCaseName, testCase);
                    }
                }
            }
        }

        Set<String> buildIdList = new HashSet<>();
        List<DeviceInfoEntity> devices = new ArrayList<>();
        Query deviceQuery = new Query(DeviceInfoEntity.KIND).setAncestor(mostRecentRun.getKey());
        for (Entity device : datastore.prepare(deviceQuery).asIterable()) {
            DeviceInfoEntity deviceEntity = DeviceInfoEntity.fromEntity(device);
            if (deviceEntity == null) {
                continue;
            }
            buildIdList.add(deviceEntity.getBuildId());
            devices.add(deviceEntity);
        }
        String footer = EmailHelper.getEmailFooter(mostRecentRun, devices, link);
        String buildId = StringUtils.join(buildIdList, ",");

        for (String testCaseName : mostRecentTestCaseResults.keySet()) {
            TestCaseResult mostRecentResult = mostRecentTestCaseResults.get(testCaseName);
            boolean previouslyFailed = failedTestCaseMap.containsKey(testCaseName);
            if (mostRecentResult == TestCaseResult.TEST_CASE_RESULT_SKIP) {
                // persist previous status
                if (previouslyFailed) {
                    skippedTestcaseFailures.add(testCaseName);
                    failingTestCases.add(
                            new TestCaseReference(failedTestCaseMap.get(testCaseName)));
                } else {
                    ++passingTestcaseCount;
                }
            } else if (mostRecentResult == TestCaseResult.TEST_CASE_RESULT_PASS) {
                ++passingTestcaseCount;
                if (previouslyFailed && !transientTestcaseFailures.contains(testCaseName)) {
                    fixedTestcases.add(testCaseName);
                }
            } else {
                if (!previouslyFailed) {
                    newTestcaseFailures.add(testCaseName);
                    failingTestCases.add(
                            new TestCaseReference(testCaseBreakageMap.get(testCaseName)));
                } else {
                    continuedTestcaseFailures.add(testCaseName);
                    failingTestCases.add(
                            new TestCaseReference(failedTestCaseMap.get(testCaseName)));
                }
            }
        }

        Set<String> acknowledgedFailures =
                separateAcknowledged(newTestcaseFailures, devices, testAcks);
        acknowledgedFailures.addAll(
                separateAcknowledged(transientTestcaseFailures, devices, testAcks));
        acknowledgedFailures.addAll(
                separateAcknowledged(continuedTestcaseFailures, devices, testAcks));

        String summary = new String();
        if (newTestcaseFailures.size() + continuedTestcaseFailures.size() > 0) {
            summary += "The following test cases failed in the latest test run:<br>";

            // Add new test case failures to top of summary in bold font.
            List<String> sortedNewTestcaseFailures = new ArrayList<>(newTestcaseFailures);
            sortedNewTestcaseFailures.sort(Comparator.naturalOrder());
            for (String testcaseName : sortedNewTestcaseFailures) {
                summary += "- " + "<b>" + testcaseName + "</b><br>";
            }

            // Add continued test case failures to summary.
            List<String> sortedContinuedTestcaseFailures =
                    new ArrayList<>(continuedTestcaseFailures);
            sortedContinuedTestcaseFailures.sort(Comparator.naturalOrder());
            for (String testcaseName : sortedContinuedTestcaseFailures) {
                summary += "- " + testcaseName + "<br>";
            }
        }
        if (fixedTestcases.size() > 0) {
            // Add fixed test cases to summary.
            summary += "<br><br>The following test cases were fixed in the latest test run:<br>";
            List<String> sortedFixedTestcases = new ArrayList<>(fixedTestcases);
            sortedFixedTestcases.sort(Comparator.naturalOrder());
            for (String testcaseName : sortedFixedTestcases) {
                summary += "- <i>" + testcaseName + "</i><br>";
            }
        }
        if (transientTestcaseFailures.size() > 0) {
            // Add transient test case failures to summary.
            summary += "<br><br>The following transient test case failures occured:<br>";
            List<String> sortedTransientTestcaseFailures =
                    new ArrayList<>(transientTestcaseFailures);
            sortedTransientTestcaseFailures.sort(Comparator.naturalOrder());
            for (String testcaseName : sortedTransientTestcaseFailures) {
                summary += "- " + testcaseName + "<br>";
            }
        }
        if (skippedTestcaseFailures.size() > 0) {
            // Add skipped test case failures to summary.
            summary += "<br><br>The following test cases have not been run since failing:<br>";
            List<String> sortedSkippedTestcaseFailures = new ArrayList<>(skippedTestcaseFailures);
            sortedSkippedTestcaseFailures.sort(Comparator.naturalOrder());
            for (String testcaseName : sortedSkippedTestcaseFailures) {
                summary += "- " + testcaseName + "<br>";
            }
        }
        if (acknowledgedFailures.size() > 0) {
            // Add acknowledged test case failures to summary.
            List<String> sortedAcknowledgedFailures = new ArrayList<>(acknowledgedFailures);
            sortedAcknowledgedFailures.sort(Comparator.naturalOrder());
            if (acknowledgedFailures.size() > 0) {
                summary +=
                        "<br><br>The following acknowledged test case failures continued to fail:<br>";
                for (String testcaseName : sortedAcknowledgedFailures) {
                    summary += "- " + testcaseName + "<br>";
                }
            }
        }

        String testName = mostRecentRun.getKey().getParent().getName();
        String uploadDateString = TimeUtil.getDateString(mostRecentRun.getStartTimestamp());
        String subject = "VTS Test Alert: " + testName + " @ " + uploadDateString;
        if (newTestcaseFailures.size() > 0) {
            String body =
                    "Hello,<br><br>New test case failure(s) in "
                            + testName
                            + " for device build ID(s): "
                            + buildId
                            + ".<br><br>"
                            + summary
                            + footer;
            try {
                messages.add(EmailHelper.composeEmail(emailAddresses, subject, body));
            } catch (MessagingException | UnsupportedEncodingException e) {
                logger.log(Level.WARNING, "Error composing email : ", e);
            }
        } else if (continuedTestcaseFailures.size() > 0) {
            String body =
                    "Hello,<br><br>Continuous test case failure(s) in "
                            + testName
                            + " for device build ID(s): "
                            + buildId
                            + ".<br><br>"
                            + summary
                            + footer;
            try {
                messages.add(EmailHelper.composeEmail(emailAddresses, subject, body));
            } catch (MessagingException | UnsupportedEncodingException e) {
                logger.log(Level.WARNING, "Error composing email : ", e);
            }
        } else if (transientTestcaseFailures.size() > 0) {
            String body =
                    "Hello,<br><br>Transient test case failure(s) in "
                            + testName
                            + " but tests all "
                            + "are passing in the latest device build(s): "
                            + buildId
                            + ".<br><br>"
                            + summary
                            + footer;
            try {
                messages.add(EmailHelper.composeEmail(emailAddresses, subject, body));
            } catch (MessagingException | UnsupportedEncodingException e) {
                logger.log(Level.WARNING, "Error composing email : ", e);
            }
        } else if (fixedTestcases.size() > 0) {
            String body =
                    "Hello,<br><br>All test cases passed in "
                            + testName
                            + " for device build ID(s): "
                            + buildId
                            + "!<br><br>"
                            + summary
                            + footer;
            try {
                messages.add(EmailHelper.composeEmail(emailAddresses, subject, body));
            } catch (MessagingException | UnsupportedEncodingException e) {
                logger.log(Level.WARNING, "Error composing email : ", e);
            }
        }
        return new TestStatusEntity(
                testName,
                mostRecentRun.getStartTimestamp(),
                passingTestcaseCount,
                failingTestCases.size(),
                failingTestCases);
    }

    /**
     * Add a task to process test run data
     *
     * @param testRunKey The key of the test run whose data process.
     */
    public static void addTask(Key testRunKey) {
        Queue queue = QueueFactory.getDefaultQueue();
        String keyString = KeyFactory.keyToString(testRunKey);
        queue.add(
                TaskOptions.Builder.withUrl(ALERT_JOB_URL)
                        .param("runKey", keyString)
                        .method(TaskOptions.Method.POST));
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        String runKeyString = request.getParameter("runKey");

        Key testRunKey;
        try {
            testRunKey = KeyFactory.stringToKey(runKeyString);
        } catch (IllegalArgumentException e) {
            logger.log(Level.WARNING, "Invalid key specified: " + runKeyString);
            return;
        }
        String testName = testRunKey.getParent().getName();

        TestStatusEntity status = null;
        Key statusKey = KeyFactory.createKey(TestStatusEntity.KIND, testName);
        try {
            status = TestStatusEntity.fromEntity(datastore.get(statusKey));
        } catch (EntityNotFoundException e) {
            // no existing status
        }
        if (status == null) {
            status = new TestStatusEntity(testName);
        }
        if (status.getUpdatedTimestamp() >= testRunKey.getId()) {
            // Another job has already updated the status first
            return;
        }
        List<String> emails = EmailHelper.getSubscriberEmails(testRunKey.getParent());

        StringBuffer fullUrl = request.getRequestURL();
        String baseUrl = fullUrl.substring(0, fullUrl.indexOf(request.getRequestURI()));
        String link =
                baseUrl + "/show_tree?testName=" + testName + "&endTime=" + testRunKey.getId();

        List<Message> messageQueue = new ArrayList<>();
        Map<String, TestCase> failedTestcaseMap = getCurrentFailures(status);
        List<TestAcknowledgmentEntity> testAcks =
                getTestCaseAcknowledgments(testRunKey.getParent());
        List<TestRunEntity> testRuns =
                getTestRuns(
                        testRunKey.getParent(), status.getUpdatedTimestamp(), testRunKey.getId());
        if (testRuns.size() == 0) return;

        TestStatusEntity newStatus =
                getTestStatus(testRuns, link, failedTestcaseMap, testAcks, emails, messageQueue);
        if (newStatus == null) {
            // No changes to status
            return;
        }

        int retries = 0;
        while (true) {
            Transaction txn = datastore.beginTransaction();
            try {
                try {
                    status = TestStatusEntity.fromEntity(datastore.get(statusKey));
                } catch (EntityNotFoundException e) {
                    // no status left
                }
                if (status == null
                        || status.getUpdatedTimestamp() >= newStatus.getUpdatedTimestamp()) {
                    txn.rollback();
                } else { // This update is most recent.
                    datastore.put(newStatus.toEntity());
                    txn.commit();
                    EmailHelper.sendAll(messageQueue);
                }
                break;
            } catch (ConcurrentModificationException
                    | DatastoreFailureException
                    | DatastoreTimeoutException e) {
                logger.log(Level.WARNING, "Retrying alert job insert: " + statusKey);
                if (retries++ >= DatastoreHelper.MAX_WRITE_RETRIES) {
                    logger.log(Level.SEVERE, "Exceeded alert job retries: " + statusKey);
                    throw e;
                }
            } finally {
                if (txn.isActive()) {
                    txn.rollback();
                }
            }
        }
    }
}
