/*
 * Copyright 2015-present 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.ui.table;

import com.google.common.collect.Sets;
import org.onosproject.ui.table.cell.DefaultCellComparator;
import org.onosproject.ui.table.cell.DefaultCellFormatter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * A simple model of table data.
 * <p>
 * Note that this is not a full MVC type model; the expected usage pattern
 * is to create an empty table, add rows (by consulting the business model),
 * sort rows (based on client request parameters), and finally produce the
 * sorted list of rows.
 * <p>
 * The table also provides a mechanism for defining how cell values for a
 * particular column should be formatted into strings, to help facilitate
 * the encoding of the table data into a JSON structure.
 * <p>
 * Note that it is expected that all values for a particular column will
 * be the same class.
 */
public class TableModel {

    private static final CellComparator DEF_CMP = DefaultCellComparator.INSTANCE;
    private static final CellFormatter DEF_FMT = DefaultCellFormatter.INSTANCE;
    private static final String EMPTY = "";

    private final String[] columnIds;
    private final Set<String> idSet;
    private final Map<String, CellComparator> comparators = new HashMap<>();
    private final Map<String, CellFormatter> formatters = new HashMap<>();
    private final List<Row> rows = new ArrayList<>();
    private final Map<String, Annot> annotations = new HashMap<>();

    /**
     * Constructs a table (devoid of data) with the given column IDs.
     *
     * @param columnIds column identifiers
     */
    public TableModel(String... columnIds) {
        checkNotNull(columnIds, "columnIds cannot be null");
        checkArgument(columnIds.length > 0, "must be at least one column");

        idSet = Sets.newHashSet(columnIds);
        if (idSet.size() != columnIds.length) {
            throw new IllegalArgumentException("duplicate column ID(s) detected");
        }

        this.columnIds = Arrays.copyOf(columnIds, columnIds.length);
    }

    private void checkId(String id) {
        checkNotNull(id, "must provide a column ID");
        if (!idSet.contains(id)) {
            throw new IllegalArgumentException("unknown column id: " + id);
        }
    }

    /**
     * Returns the number of rows in this table model.
     *
     * @return number of rows
     */
    public int rowCount() {
        return rows.size();
    }

    /**
     * Returns the number of columns in this table model.
     *
     * @return number of columns
     */
    public int columnCount() {
        return columnIds.length;
    }

    /**
     * Returns the array of column IDs for this table model.
     * <p>
     * Implementation note: we are knowingly passing you a reference to
     * our internal array to avoid copying. Don't mess with it. It's your
     * table you'll break if you do!
     *
     * @return the column identifiers
     */
    public String[] getColumnIds() {
        return columnIds;
    }

    /**
     * Returns the raw {@link Row} representation of the rows in this table.
     *
     * @return raw table rows
     */
    public Row[] getRows() {
        return rows.toArray(new Row[rows.size()]);
    }

    /**
     * Inserts a new annotation.
     *
     * @param key key of annotation
     * @param value value of annotation
     */
    public void addAnnotation(String key, Object value) {
        Annot annot = new Annot(key, value);
        annotations.put(key, annot);
    }

    /**
     * Returns the annotations in this table.
     *
     * @return annotations
     */
    public Collection<Annot> getAnnotations() {
        Collection<Annot> annots = new ArrayList<>(annotations.size());
        annotations.forEach((k, v) -> annots.add(v));
        return annots;
    }

    /**
     * Sets a cell comparator for the specified column.
     *
     * @param columnId column identifier
     * @param comparator comparator to use
     */
    public void setComparator(String columnId, CellComparator comparator) {
        checkNotNull(comparator, "must provide a comparator");
        checkId(columnId);
        comparators.put(columnId, comparator);
    }

    /**
     * Returns the cell comparator to use on values in the specified column.
     *
     * @param columnId column identifier
     * @return an appropriate cell comparator
     */
    private CellComparator getComparator(String columnId) {
        checkId(columnId);
        CellComparator cmp = comparators.get(columnId);
        return cmp == null ? DEF_CMP : cmp;
    }

    /**
     * Sets a cell formatter for the specified column.
     *
     * @param columnId column identifier
     * @param formatter formatter to use
     */
    public void setFormatter(String columnId, CellFormatter formatter) {
        checkNotNull(formatter, "must provide a formatter");
        checkId(columnId);
        formatters.put(columnId, formatter);
    }

    /**
     * Returns the cell formatter to use on values in the specified column.
     *
     * @param columnId column identifier
     * @return an appropriate cell formatter
     */
    public CellFormatter getFormatter(String columnId) {
        checkId(columnId);
        CellFormatter fmt = formatters.get(columnId);
        return fmt == null ? DEF_FMT : fmt;
    }

    /**
     * Adds a row to the table model.
     *
     * @return the row, for chaining
     */
    public Row addRow() {
        Row r = new Row();
        rows.add(r);
        return r;
    }

    /**
     * Sorts the table rows based on the specified columns, in the
     * specified directions. The second column is optional, and can be
     * disregarded by passing null into id2 and dir2.
     *
     * @param id1 first column identifier
     * @param dir1 first column sort direction
     * @param id2 second column identifier (may be null)
     * @param dir2 second column sort direction (may be null)
     */
    public void sort(String id1, SortDir dir1, String id2, SortDir dir2) {
        Collections.sort(rows, new RowComparator(id1, dir1, id2, dir2));
    }


    /** Designates sorting direction. */
    public enum SortDir {
        /** Designates an ascending sort. */
        ASC,
        /** Designates a descending sort. */
        DESC
    }

    private boolean nullOrEmpty(String s) {
        return s == null || EMPTY.equals(s.trim());
    }

    /**
     * Row comparator.
     */
    private class RowComparator implements Comparator<Row> {
        private final String id1;
        private final SortDir dir1;
        private final String id2;
        private final SortDir dir2;
        private final CellComparator cc1;
        private final CellComparator cc2;

        /**
         * Constructs a row comparator based on the specified
         * column identifiers and sort directions. Note that id2 and dir2 may
         * be null.
         *
         * @param id1 first column identifier
         * @param dir1 first column sort direction
         * @param id2 second column identifier
         * @param dir2 second column sort direction
         */
        public RowComparator(String id1, SortDir dir1, String id2, SortDir dir2) {
            this.id1 = id1;
            this.dir1 = dir1;
            this.id2 = id2;
            this.dir2 = dir2;
            cc1 = getComparator(id1);
            cc2 = nullOrEmpty(id2) ? null : getComparator(id2);
        }

        @Override
        public int compare(Row a, Row b) {
            Object cellA = a.get(id1);
            Object cellB = b.get(id1);
            int result = cc1.compare(cellA, cellB);
            result = dir1 == SortDir.ASC ? result : -result;

            if (result == 0 && cc2 != null) {
                cellA = a.get(id2);
                cellB = b.get(id2);
                result = cc2.compare(cellA, cellB);
                result = dir2 == SortDir.ASC ? result : -result;
            }
            return result;
        }
    }

    /**
     * Model of an annotation.
     */
    public class Annot {
        private final String key;
        private final Object value;

        /**
         * Constructs an annotation with the given key and value.
         *
         * @param key the key
         * @param value the value
         */
        public Annot(String key, Object value) {
            this.key = key;
            this.value = value;
        }

        /**
         * Returns the annotation's key.
         *
         * @return key
         */
        public String key() {
            return key;
        }

        /**
         * Returns the annotation's value.
         *
         * @return value
         */
        public Object value() {
            return value;
        }

        /**
         * Returns the value as a string.
         * This default implementation uses the value's toString() method.
         *
         * @return the value as a string
         */
        public String valueAsString() {
            return value.toString();
        }
    }

    /**
     * Model of a row.
     */
    public class Row {
        private final Map<String, Object> cells = new HashMap<>();

        /**
         * Sets the cell value for the given column of this row.
         *
         * @param columnId column identifier
         * @param value value to set
         * @return self, for chaining
         */
        public Row cell(String columnId, Object value) {
            checkId(columnId);
            cells.put(columnId, value);
            return this;
        }

        /**
         * Returns the value of the cell in the given column for this row.
         *
         * @param columnId column identifier
         * @return cell value
         */
        public Object get(String columnId) {
            return cells.get(columnId);
        }

        /**
         * Returns the value of the cell as a string, using the
         * formatter appropriate for the column.
         *
         * @param columnId column identifier
         * @return formatted cell value
         */
        String getAsString(String columnId) {
            return getFormatter(columnId).format(get(columnId));
        }

        /**
         * Returns the row as an array of formatted strings.
         *
         * @return the formatted row data
         */
        public String[] getAsFormattedStrings() {
            List<String> formatted = new ArrayList<>(columnCount());
            for (String c : columnIds) {
                formatted.add(getAsString(c));
            }
            return formatted.toArray(new String[formatted.size()]);
        }
    }

    private static final String DESC = "desc";

    /**
     * Returns the appropriate sort direction for the given string.
     * <p>
     * The expected strings are "asc" for {@link SortDir#ASC ascending} and
     * "desc" for {@link SortDir#DESC descending}. Any other value will
     * default to ascending.
     *
     * @param s sort direction string encoding
     * @return sort direction
     */
    public static SortDir sortDir(String s) {
        return !DESC.equals(s) ? SortDir.ASC : SortDir.DESC;
    }
}
