/*
 * Copyright 2015 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;
    }
}
