/*
 * Copyright (C) 2016 Jorge Ruesga
 *
 * 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.ruesga.gerrit.plugins.fcm.handlers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.events.ChangeEvent;
import com.google.gerrit.extensions.events.RevisionEvent;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.IdentifiedUser.GenericFactory;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.WatchConfig.NotifyType;
import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gerrit.server.query.QueryResult;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;
import com.ruesga.gerrit.plugins.fcm.messaging.Notification;
import com.ruesga.gerrit.plugins.fcm.workers.FcmUploaderWorker;

public abstract class EventHandler {

    static final Logger log =
            LoggerFactory.getLogger(EventHandler.class);

    private final String pluginName;
    private final FcmUploaderWorker uploader;
    private final AllProjectsName allProjectsName;
    private final ChangeQueryBuilder cqb;
    private final ChangeQueryProcessor cqp;
    private final Provider<InternalAccountQuery> accountQueryProvider;
    private final GenericFactory identifiedUserFactory;
    private final Gson gson;

    public EventHandler(
            @PluginName String pluginName,
            FcmUploaderWorker uploader,
            AllProjectsName allProjectsName,
            ChangeQueryBuilder cqb,
            ChangeQueryProcessor cqp,
            Provider<InternalAccountQuery> accountQueryProvider,
            CapabilityControl.Factory capabilityControlFactory,
            GenericFactory identifiedUserFactory) {
        super();
        this.pluginName = pluginName;
        this.uploader = uploader;
        this.allProjectsName = allProjectsName;
        this.cqb = cqb;
        this.cqp = cqp;
        this.accountQueryProvider = accountQueryProvider;
        this.identifiedUserFactory = identifiedUserFactory;
        this.gson = new GsonBuilder().create();
    }

    protected abstract int getEventType();

    protected abstract NotifyType getNotifyType();

    protected Gson getSerializer() {
        return this.gson;
    }

    protected Notification createNotification(ChangeEvent event) {
        Notification notification = new Notification();
        notification.event = getEventType();
        notification.when = event.getWhen().getTime() / 1000L;
        notification.who = event.getWho();
        notification.change = event.getChange().changeId;
        notification.legacyChangeId = event.getChange()._number;
        notification.project = event.getChange().project;
        notification.branch = event.getChange().branch;
        notification.topic = event.getChange().topic;
        notification.subject = StringUtils.abbreviate(
                event.getChange().subject, 100);
        if (event instanceof RevisionEvent) {
            notification.revision =
                    ((RevisionEvent) event).getRevision().commit.commit;
        }
        return notification;
    }

    protected void notify(Notification notification, ChangeEvent event) {
        // Check if this event should be notified
        if (event.getNotify().equals(NotifyHandling.NONE)) {
            if (log.isDebugEnabled()) {
                log.debug(
                    String.format("[%s] Notify event %d is not enabled: %s",
                        pluginName, getEventType(), gson.toJson(notification)));
            }
            return;
        }

        // Obtain information about the accounts that need to be
        // notified related to this event
        List<Integer> notifiedUsers = obtainNotifiedAccounts(event);
        if (notifiedUsers.isEmpty()) {
            // Nobody to notify about this event
            return;
        }

        // Perform notification
        if (log.isDebugEnabled()) {
            log.debug(String.format("[%s] Sending notification %s to %s",
                    pluginName, gson.toJson(notification),
                    gson.toJson(notifiedUsers)));
        }
        this.uploader.notifyTo(notifiedUsers, notification);
    }

    private List<Integer> obtainNotifiedAccounts(ChangeEvent event) {
        Set<Integer> notifiedUsers = new HashSet<>();
        ChangeInfo change = event.getChange();
        NotifyHandling notifyTo = event.getNotify();

        // 1.- Owner of the change
        notifiedUsers.add(change.owner._accountId);

        // 2.- Reviewers
        if (notifyTo.equals(NotifyHandling.OWNER_REVIEWERS) ||
                notifyTo.equals(NotifyHandling.ALL)) {
            if (change.reviewers != null) {
                for (ReviewerState state : change.reviewers.keySet()) {
                    Collection<AccountInfo> accounts =
                            change.reviewers.get(state);
                    for (AccountInfo account : accounts) {
                        notifiedUsers.add(account._accountId);
                    }
                }
            }
        }

        // 3.- Watchers
        ChangeData changeData = obtainChangeData(change);
        notifiedUsers.addAll(getWatchers(getNotifyType(), changeData));

        // 4.- Remove the author of this event (he doesn't need to get
        // the notification)
        notifiedUsers.remove(event.getWho()._accountId);

        return new ArrayList<>(notifiedUsers);
    }

    public final Set<Integer> getWatchers(NotifyType type, ChangeData change) {
        Set<Integer> watchers = new HashSet<>();
        try {
            Set<Account.Id> projectWatchers = new HashSet<>();
            for (AccountState a : accountQueryProvider.get().byWatchedProject(
                    change.project())) {
                Account.Id accountId = a.getAccount().getId();
                for (Map.Entry<ProjectWatchKey, Set<NotifyType>> e : a.getProjectWatches().entrySet()) {
                    if (change.project().equals(e.getKey().project())
                            && add(watchers, accountId, e.getKey(), e.getValue(), type, change)) {
                        // We only want to prevent matching All-Projects if this filter hits
                        projectWatchers.add(accountId);
                    }
                }
            }

            for (AccountState a : accountQueryProvider.get().byWatchedProject(
                    allProjectsName)) {
              for (Map.Entry<ProjectWatchKey, Set<NotifyType>> e : a.getProjectWatches().entrySet()) {
                if (allProjectsName.equals(e.getKey().project())) {
                  Account.Id accountId = a.getAccount().getId();
                  if (!projectWatchers.contains(accountId)) {
                    add(watchers, accountId, e.getKey(), e.getValue(), type, change);
                  }
                }
              }
            }

        } catch (OrmException ex) {
            log.error(String.format(
                    "[%s] Failed to obtain watchers", pluginName), ex);
        }
        return watchers;
    }

    private boolean add(Set<Integer> watchers, Account.Id accountId,
            ProjectWatchKey key, Set<NotifyType> watchedTypes, NotifyType type,
            ChangeData change) throws OrmException {
        IdentifiedUser user = identifiedUserFactory.create(accountId);

        try {
            if (filterMatch(user, key.filter(), change)) {
                // If we are set to notify on this type, add the user.
                // Otherwise, still return true to stop notifications for this user.
                if (watchedTypes.contains(type)) {
                    watchers.add(accountId.get());
                }
                return true;
            }
        } catch (QueryParseException e) {
            // Ignore broken filter expressions.
        }
        return false;
    }

    private boolean filterMatch(
            CurrentUser user, String filter, ChangeData change)
            throws OrmException, QueryParseException {
        ChangeQueryBuilder qb = cqb.asUser(user);
        Predicate<ChangeData> p = qb.is_visible();

        if (filter != null) {
            Predicate<ChangeData> filterPredicate = qb.parse(filter);
            if (p == null) {
                p = filterPredicate;
            } else {
                p = Predicate.and(filterPredicate, p);
            }
        }
        return p == null || p.asMatchable().match(change);
    }

    private ChangeData obtainChangeData(ChangeInfo change) {
        try {
            QueryResult<ChangeData> changeQuery =
                    cqp.query(cqb.parse("change:" + change._number));
            List<ChangeData> changeQueryResults = changeQuery.entities();
            if (changeQueryResults == null || changeQueryResults.isEmpty()) {
                log.warn(String.format("[%s] No change found for %s",
                        pluginName, change._number));
                return null;
            }
            return changeQueryResults.get(0);

        } catch (Exception ex) {
            log.error(String.format("[%s] Failed to obtain change data: %d",
                    pluginName, change._number), ex);
        }
        return null;
    }

    protected String formatAccount(AccountInfo account) {
        if (account.name != null) {
            return account.name;
        }
        if (account.username != null) {
            return account.username;
        }
        return account.email;
    }
}