/*
 * 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 org.apache.skywalking.oap.server.core.analysis.metrics;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
import org.apache.skywalking.oap.server.library.util.StringUtil;

import static org.apache.skywalking.oap.server.core.analysis.metrics.DataLabel.GENERAL_LABEL_NAME;

/**
 * DataTable includes a hashmap to store string key and long value. It enhanced the serialization capability.
 */
@ToString
@EqualsAndHashCode
public class DataTable implements StorageDataComplexObject<DataTable> {
    private HashMap<String, Long> data;

    public DataTable() {
        data = new HashMap<>();
    }

    public DataTable(int initialCapacity) {
        data = new HashMap<>(initialCapacity);
    }

    public DataTable(String data) {
        this();
        toObject(data);
    }

    public Long get(String key) {
        return data.get(key);
    }

    public void put(String key, Long value) {
        data.put(key, value);
    }

    public void put(DataLabel labels, Long value) {
        data.put(labels.toString(), value);
    }

    /**
     * Accumulate the value with existing value in the same given key.
     */
    public void valueAccumulation(String key, Long value) {
        Long element = data.get(key);
        if (element == null) {
            element = value;
        } else {
            element += value;
        }
        data.put(key, element);
    }

    /**
     * @return the sum of all values.
     */
    public long sumOfValues() {
        return data.values().stream().mapToLong(element -> element).sum();
    }

    public boolean keysEqual(DataTable that) {
        if (this.data.keySet().size() != that.data.keySet().size()) {
            return false;
        }
        return this.data.keySet().equals(that.data.keySet());
    }

    public List<String> sortedKeys(Comparator<String> keyComparator) {
        return data.keySet().stream().sorted(keyComparator).collect(Collectors.toList());
    }

    public List<Long> sortedValues(Comparator<String> keyComparator) {
        final List<String> collect = data.keySet().stream().sorted(keyComparator).collect(Collectors.toList());
        List<Long> values = new ArrayList<>(collect.size());
        collect.forEach(key -> values.add(data.get(key)));
        return values;
    }

    public Set<String> keys() {
        return data.keySet();
    }

    public boolean hasData() {
        return !data.isEmpty();
    }

    public boolean hasKey(String key) {
        return data.containsKey(key);
    }

    public int size() {
        return data.size();
    }

    @Override
    public String toStorageData() {
        StringBuilder builder = new StringBuilder();

        this.data.forEach((key, value) -> {
            if (builder.length() != 0) {
                // For the first element.
                builder.append(Const.ARRAY_SPLIT);
            }
            builder.append(key).append(Const.KEY_VALUE_SPLIT).append(value);
        });
        return builder.toString();
    }

    @Override
    public void toObject(String data) {
        String[] keyValues = data.split(Const.ARRAY_PARSER_SPLIT);
        for (String keyValue : keyValues) {
            int i = keyValue.lastIndexOf(Const.KEY_VALUE_SPLIT);
            if (i > 0) {
                String key = keyValue.substring(0, i);
                String value = keyValue.substring(i + 1);
                if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(value)) {
                    this.data.put(key, Long.parseLong(value));
                }
            }
        }
    }

    @Override
    public void copyFrom(final DataTable source) {
        this.append(source);
    }

    public DataTable append(DataTable dataTable) {
        dataTable.data.forEach((key, value) -> {
            Long current = this.data.get(key);
            if (current == null) {
                current = value;
            } else {
                current += value;
            }
            this.data.put(key, current);
        });
        return this;
    }

    public DataTable setMaxValue(DataTable dataTable) {
        dataTable.data.forEach((key, value) -> {
            Long current = this.data.get(key);
            if (current == null) {
                current = value;
            } else {
                if (current < value) {
                    current = value;
                }
            }
            this.data.put(key, current);
        });
        return this;
    }

    public DataTable setMinValue(DataTable dataTable) {
        dataTable.data.forEach((key, value) -> {
            Long current = this.data.get(key);
            if (current == null) {
                current = value;
            } else {
                if (current > value) {
                    current = value;
                }
            }
            this.data.put(key, current);
        });
        return this;
    }

    public Map<String, Set<String>> buildLabelIndex() {
        Map<String, Set<String>> labelIndex = new HashMap<>();
        for (String key : data.keySet()) {
            if (key.startsWith(Const.LEFT_BRACE)) {
                String labels = key.substring(1, key.length() - 1);
                if (StringUtil.isNotEmpty(labels)) {
                    String[] labelsArr = labels.split(Const.COMMA);
                    for (String label : labelsArr) {
                        labelIndex.computeIfAbsent(label, keys -> new HashSet<>()).add(key);
                    }
                }
            } else {
                labelIndex.computeIfAbsent(GENERAL_LABEL_NAME + Const.EQUAL + key, keys -> new HashSet<>()).add(key);
            }
        }
        return labelIndex;
    }
}
