/*
 * Copyright 2017 HugeGraph Authors
 *
 * 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 com.baidu.hugegraph.util;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import com.google.common.base.Functions;
import com.google.common.collect.Ordering;

/**
 * Reference: https://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values
 */
public class OrderLimitMap<K extends Comparable<K>, V extends Comparable<V>>
       extends TreeMap<K, V> {

    private static final long serialVersionUID = 756490437953358633L;

    private final int capacity;
    private final Map<K, V> valueMap;

    private static <V extends Comparable<V>> Ordering<? super V> incr() {
        return Ordering.from((V o1, V o2) -> o1.compareTo(o2));
    }

    private static <V extends Comparable<V>> Ordering<? super V> decr() {
        return Ordering.from((V o1, V o2) -> -o1.compareTo(o2));
    }

    public OrderLimitMap(int capacity) {
        this(capacity, false);
    }

    public OrderLimitMap(int capacity, boolean incr) {
        this(capacity, incr ? incr() : decr(), new HashMap<>());
    }

    private OrderLimitMap(int capacity, Ordering<? super V> ordering,
                          HashMap<K, V> valueMap) {
        /*
         * onResultOf: for getting the value for the key from value map
         * compound: keep insertion order
         */
        super(ordering.onResultOf(Functions.forMap(valueMap))
                      .compound(Ordering.natural()));
        E.checkArgument(capacity > 0, "The capacity must be > 0");
        this.capacity = capacity;
        this.valueMap = valueMap;
    }

    @Override
    public V put(K k, V v) {
        if (this.valueMap.containsKey(k)) {
            super.remove(k);
        } else if (this.valueMap.size() >= this.capacity) {
            K key = super.lastKey();
            super.remove(key);
            this.valueMap.remove(key);
        }
        this.valueMap.put(k, v);
        return super.put(k, v);
    }

    @Override
    public V get(Object key) {
        return this.valueMap.get(key);
    }

    @Override
    public V getOrDefault(Object key, V defaultValue) {
        return this.valueMap.getOrDefault(key, defaultValue);
    }

    @Override
    public boolean containsKey(Object key) {
        return this.valueMap.containsKey(key);
    }

    public Map<K, V> topN(int n) {
        E.checkArgument(n > 0, "'N' Must be positive, but got '%s'", n);
        Map<K, V> top = InsertionOrderUtil.newMap();
        int i = 0;
        for (Map.Entry<K, V> entry : this.entrySet()) {
            top.put(entry.getKey(), entry.getValue());
            if (++i >= n) {
                break;
            }
        }
        return top;
    }
}
