/*
 * 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 com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
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.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.AnonymousUser;
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.GroupBackend;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.git.NotifyConfig;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
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.gerrit.server.query.change.SingleGroupUser;
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;

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

public abstract class EventHandler {

    private 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 ProjectCache projectCache;
    private final GroupBackend groupBackend;
    private final Provider<InternalAccountQuery> accountQueryProvider;
    private final GenericFactory identifiedUserFactory;
    private final Provider<AnonymousUser> anonymousProvider;
    private final Gson gson;

    public EventHandler(
            @PluginName String pluginName,
            FcmUploaderWorker uploader,
            AllProjectsName allProjectsName,
            ChangeQueryBuilder cqb,
            ChangeQueryProcessor cqp,
            ProjectCache projectCache,
            GroupBackend groupBackend,
            Provider<InternalAccountQuery> accountQueryProvider,
            GenericFactory identifiedUserFactory,
            Provider<AnonymousUser> anonymousProvider) {
        super();
        this.pluginName = pluginName;
        this.uploader = uploader;
        this.allProjectsName = allProjectsName;
        this.cqb = cqb;
        this.cqp = cqp;
        this.projectCache = projectCache;
        this.groupBackend = groupBackend;
        this.accountQueryProvider = accountQueryProvider;
        this.identifiedUserFactory = identifiedUserFactory;
        this.anonymousProvider = anonymousProvider;
        this.gson = new GsonBuilder().create();
    }

    protected abstract int getEventType();

    protected abstract NotifyType getNotifyType();

    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);
        if (changeData != null) {
            notifiedUsers.addAll(getWatchers(getNotifyType(), changeData,
                    !safeBoolean(change.workInProgress) && !safeBoolean(change.isPrivate)));
        }

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

        return new ArrayList<>(notifiedUsers);
    }

    private Set<Integer> getWatchers(NotifyType type, ChangeData change, boolean includeWatchersFromNotifyConfig) {
        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, ImmutableSet<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, ImmutableSet<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);
                        }
                    }
                }
            }

            if (includeWatchersFromNotifyConfig) {
                ProjectState projectState = projectCache.get(change.project());
                if (projectState != null) {
                    for (ProjectState state : projectState.tree()) {
                        for (NotifyConfig nc : state.getConfig().getNotifyConfigs()) {
                            if (nc.isNotify(type)) {
                                try {
                                    add(watchers, nc, change);
                                } catch (QueryParseException e) {
                                    log.warn(
                                        "Project {} has invalid notify {} filter \"{}\": {}",
                                        state.getName(),
                                        nc.getName(),
                                        nc.getFilter(),
                                        e.getMessage());
                                }
                            }
                        }
                    }
                }
            }

        } 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 void add(Set<Integer> watchers, NotifyConfig nc, ChangeData change)
            throws OrmException, QueryParseException {
        for (GroupReference ref : nc.getGroups()) {
            CurrentUser user = new SingleGroupUser(ref.getUUID());
            if (filterMatch(user, nc.getFilter(), change)) {
                deliverToMembers(watchers, ref.getUUID());
            }
        }
    }

    private boolean filterMatch(
            CurrentUser user, String filter, ChangeData change)
            throws OrmException, QueryParseException {
        ChangeQueryBuilder qb;
        Predicate<ChangeData> p = null;
        if (user == null) {
            qb = cqb.asUser(anonymousProvider.get());
        } else {
            qb = cqb.asUser(user);
            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;
    }

    private void deliverToMembers(Set<Integer> watchers, AccountGroup.UUID startUUID) {
        Set<AccountGroup.UUID> seen = new HashSet<>();
        List<AccountGroup.UUID> q = new ArrayList<>();

        seen.add(startUUID);
        q.add(startUUID);

        while (!q.isEmpty()) {
            AccountGroup.UUID uuid = q.remove(q.size() - 1);
            GroupDescription.Basic group = groupBackend.get(uuid);
            if (group == null) {
                continue;
            }

            if (!(group instanceof GroupDescription.Internal)) {
                // Non-internal groups cannot be expanded by the server.
                continue;
            }

            GroupDescription.Internal ig = (GroupDescription.Internal) group;
            for (Account.Id id : ig.getMembers()) {
                watchers.add(id.get());
            }
            for (AccountGroup.UUID m : ig.getSubgroups()) {
                if (seen.add(m)) {
                    q.add(m);
                }
            }
        }
    }

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

    boolean safeBoolean(Boolean value) {
        return value != null && value;
    }
}
