/*
 * Copyright 2014 Open Networking Laboratory
 *
 * 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 org.onosproject.store.service.impl;

import com.google.common.base.MoreObjects;
import net.jodah.expiringmap.ExpiringMap;
import net.jodah.expiringmap.ExpiringMap.ExpirationListener;
import net.jodah.expiringmap.ExpiringMap.ExpirationPolicy;
import net.kuujo.copycat.cluster.Member;
import net.kuujo.copycat.event.EventHandler;
import net.kuujo.copycat.event.LeaderElectEvent;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.cluster.messaging.ClusterMessage;
import org.onosproject.store.service.DatabaseService;
import org.onosproject.store.service.VersionedValue;
import org.onosproject.store.service.impl.DatabaseStateMachine.State;
import org.onosproject.store.service.impl.DatabaseStateMachine.TableMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.onlab.util.Tools.namedThreads;

/**
 * Plugs into the database update stream and track the TTL of entries added to
 * the database. For tables with pre-configured finite TTL, this class has
 * mechanisms for expiring (deleting) old, expired entries from the database.
 */
public class DatabaseEntryExpirationTracker implements
        DatabaseUpdateEventListener, EventHandler<LeaderElectEvent> {

    private static final ExecutorService THREAD_POOL =
            Executors.newCachedThreadPool(namedThreads("onos-db-stale-entry-expirer-%d"));

    private final Logger log = LoggerFactory.getLogger(getClass());

    private final DatabaseService databaseService;
    private final ClusterCommunicationService clusterCommunicator;

    private final Member localMember;
    private final ControllerNode localNode;
    private final AtomicBoolean isLocalMemberLeader = new AtomicBoolean(false);

    private final Map<String, Map<DatabaseRow, Long>> tableEntryExpirationMap = new HashMap<>();

    private final ExpirationListener<DatabaseRow, Long> expirationObserver = new ExpirationObserver();

    DatabaseEntryExpirationTracker(
            Member localMember,
            ControllerNode localNode,
            ClusterCommunicationService clusterCommunicator,
            DatabaseService databaseService) {
        this.localMember = localMember;
        this.localNode = localNode;
        this.clusterCommunicator = clusterCommunicator;
        this.databaseService = databaseService;
    }

    @Override
    public void tableModified(TableModificationEvent event) {
        log.debug("{}: Received {}", localNode.id(), event);

        if (!tableEntryExpirationMap.containsKey(event.tableName())) {
            return;
        }

        Map<DatabaseRow, Long> map = tableEntryExpirationMap.get(event.tableName());
        DatabaseRow row = new DatabaseRow(event.tableName(), event.key());
        Long eventVersion = event.value().version();

        switch (event.type()) {
        case ROW_DELETED:
            map.remove(row, eventVersion);
            if (isLocalMemberLeader.get()) {
                log.debug("Broadcasting {} to the entire cluster", event);
                clusterCommunicator.broadcastIncludeSelf(new ClusterMessage(
                        localNode.id(), DatabaseStateMachine.DATABASE_UPDATE_EVENTS,
                        ClusterMessagingProtocol.DB_SERIALIZER.encode(event)));
            }
            break;
        case ROW_ADDED:
        case ROW_UPDATED:
            // To account for potential reordering of notifications,
            // check to make sure we are replacing an old version with a new version
            Long currentVersion = map.get(row);
            if (currentVersion == null || currentVersion < eventVersion) {
                map.put(row, eventVersion);
            }
            break;
        default:
            break;
        }
    }

    @Override
    public void tableCreated(TableMetadata metadata) {
        log.debug("Received a table created event {}", metadata);
        if (metadata.expireOldEntries()) {
            tableEntryExpirationMap.put(metadata.tableName(), ExpiringMap.builder()
                    .expiration(metadata.ttlMillis(), TimeUnit.MILLISECONDS)
                    .expirationListener(expirationObserver)
                    .expirationPolicy(ExpirationPolicy.CREATED).build());
        }
    }

    @Override
    public void tableDeleted(String tableName) {
        log.debug("Received a table deleted event for table ({})", tableName);
        tableEntryExpirationMap.remove(tableName);
    }

    private class ExpirationObserver implements
            ExpirationListener<DatabaseRow, Long> {
        @Override
        public void expired(DatabaseRow row, Long version) {
            THREAD_POOL.submit(new ExpirationTask(row, version));
        }
    }

    private class ExpirationTask implements Runnable {

        private final DatabaseRow row;
        private final Long version;

        public ExpirationTask(DatabaseRow row, Long version) {
            this.row = row;
            this.version = version;
        }

        @Override
        public void run() {
            log.trace("Received an expiration event for {}, version: {}", row, version);
            Map<DatabaseRow, Long> map = tableEntryExpirationMap.get(row.tableName);
            try {
                if (isLocalMemberLeader.get()) {
                    if (!databaseService.removeIfVersionMatches(row.tableName,
                            row.key, version)) {
                        log.info("Entry in database was updated right before its expiration.");
                    } else {
                        log.debug("Successfully expired old entry with key ({}) from table ({})",
                                row.key, row.tableName);
                    }
                } else {
                    // Only the current leader will expire keys from database.
                    // Everyone else function as standby just in case they need to take over
                    if (map != null) {
                        map.putIfAbsent(row, version);
                    }
                }

            } catch (Exception e) {
                log.warn("Failed to delete entry from the database after ttl "
                        + "expiration. Operation will be retried.", e);
                map.putIfAbsent(row, version);
            }
        }
    }

    @Override
    public void handle(LeaderElectEvent event) {
        isLocalMemberLeader.set(localMember.equals(event.leader()));
        if (isLocalMemberLeader.get()) {
            log.info("{} is now the leader of Raft cluster", localNode.id());
        }
    }

    /**
     * Wrapper class for a database row identifier.
     */
    private class DatabaseRow {

        String tableName;
        String key;

        public DatabaseRow(String tableName, String key) {
            this.tableName = tableName;
            this.key = key;
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                .add("tableName", tableName)
                .add("key", key)
                .toString();
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof DatabaseRow)) {
                return false;
            }
            DatabaseRow that = (DatabaseRow) obj;

            return Objects.equals(this.tableName, that.tableName)
                    && Objects.equals(this.key, that.key);
        }

        @Override
        public int hashCode() {
            return Objects.hash(tableName, key);
        }
    }

    @Override
    public void snapshotInstalled(State state) {
        if (!tableEntryExpirationMap.isEmpty()) {
            return;
        }
        log.debug("Received a snapshot installed notification");
        for (String tableName : state.getTableNames()) {

            TableMetadata metadata = state.getTableMetadata(tableName);
            if (!metadata.expireOldEntries()) {
                continue;
            }

            Map<DatabaseRow, Long> tableExpirationMap = ExpiringMap.builder()
                    .expiration(metadata.ttlMillis(), TimeUnit.MILLISECONDS)
                    .expirationListener(expirationObserver)
                    .expirationPolicy(ExpirationPolicy.CREATED).build();
            for (Map.Entry<String, VersionedValue> entry : state.getTable(tableName).entrySet()) {
                tableExpirationMap.put(new DatabaseRow(tableName, entry.getKey()), entry.getValue().version());
            }

            tableEntryExpirationMap.put(tableName, tableExpirationMap);
        }
    }
}
