/*
 * 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 org.junit.Test;
import org.onosproject.ui.table.TableModel.SortDir;
import org.onosproject.ui.table.cell.DefaultCellFormatter;
import org.onosproject.ui.table.cell.HexFormatter;

import java.util.Collection;

import static org.junit.Assert.*;

/**
 * Unit tests for {@link TableModel}.
 */
public class TableModelTest {

    private static final String UNEX_SORT = "unexpected sort: index ";

    private static final String FOO = "foo";
    private static final String BAR = "bar";
    private static final String ZOO = "zoo";

    private enum StarWars {
        LUKE_SKYWALKER, LEIA_ORGANA, HAN_SOLO, C3PO, R2D2, JABBA_THE_HUTT
    }

    private static class ParenFormatter implements CellFormatter {
        @Override
        public String format(Object value) {
            return "(" + value + ")";
        }
    }

    private TableModel tm;
    private TableModel.Row[] rows;
    private TableModel.Row row;
    private CellFormatter fmt;

    @Test(expected = NullPointerException.class)
    public void guardAgainstNull() {
        tm = new TableModel(null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void guardAgainstEmpty() {
        tm = new TableModel();
    }

    @Test(expected = IllegalArgumentException.class)
    public void guardAgainstDuplicateCols() {
        tm = new TableModel(FOO, BAR, FOO);
    }

    @Test
    public void basic() {
        tm = new TableModel(FOO, BAR);
        assertEquals("column count", 2, tm.columnCount());
        assertEquals("row count", 0, tm.rowCount());
    }

    @Test
    public void defaultFormatter() {
        tm = new TableModel(FOO);
        fmt = tm.getFormatter(FOO);
        assertTrue("Wrong formatter", fmt instanceof DefaultCellFormatter);
    }

    @Test(expected = IllegalArgumentException.class)
    public void formatterBadColumn() {
        tm = new TableModel(FOO);
        fmt = tm.getFormatter(BAR);
    }

    @Test
    public void altFormatter() {
        tm = new TableModel(FOO, BAR);
        tm.setFormatter(BAR, new ParenFormatter());

        fmt = tm.getFormatter(FOO);
        assertTrue("Wrong formatter", fmt instanceof DefaultCellFormatter);
        assertEquals("Wrong result", "2", fmt.format(2));

        fmt = tm.getFormatter(BAR);
        assertTrue("Wrong formatter", fmt instanceof ParenFormatter);
        assertEquals("Wrong result", "(2)", fmt.format(2));
    }

    @Test
    public void emptyRow() {
        tm = new TableModel(FOO, BAR);
        tm.addRow();
        assertEquals("bad row count", 1, tm.rowCount());
    }

    @Test(expected = IllegalArgumentException.class)
    public void rowBadColumn() {
        tm = new TableModel(FOO, BAR);
        tm.addRow().cell(ZOO, 2);
    }

    @Test
    public void simpleRow() {
        tm = new TableModel(FOO, BAR);
        tm.addRow().cell(FOO, 3).cell(BAR, true);
        assertEquals("bad row count", 1, tm.rowCount());
        row = tm.getRows()[0];
        assertEquals("bad cell", 3, row.get(FOO));
        assertEquals("bad cell", true, row.get(BAR));
    }

    private static final String ONE = "one";
    private static final String TWO = "two";
    private static final String THREE = "three";
    private static final String FOUR = "four";
    private static final String ELEVEN = "eleven";
    private static final String TWELVE = "twelve";
    private static final String TWENTY = "twenty";
    private static final String THIRTY = "thirty";

    private static final String[] NAMES = {
            FOUR,
            THREE,
            TWO,
            ONE,
            ELEVEN,
            TWELVE,
            THIRTY,
            TWENTY,
    };
    private static final String[] SORTED_NAMES = {
            ELEVEN,
            FOUR,
            ONE,
            THIRTY,
            THREE,
            TWELVE,
            TWENTY,
            TWO,
    };

    private static final int[] NUMBERS = {
        4, 3, 2, 1, 11, 12, 30, 20
    };

    private static final int[] SORTED_NUMBERS = {
        1, 2, 3, 4, 11, 12, 20, 30
    };

    private static final String[] SORTED_HEX = {
        "0x1", "0x2", "0x3", "0x4", "0xb", "0xc", "0x14", "0x1e"
    };

    @Test
    public void verifyTestData() {
        // not a unit test per se, but will fail if we don't keep
        // the three test arrays in sync
        int nalen = NAMES.length;
        int snlen = SORTED_NAMES.length;
        int nulen = NUMBERS.length;

        if (nalen != snlen || nalen != nulen) {
            fail("test data array size discrepancy");
        }
    }

    private void initUnsortedTable() {
        tm = new TableModel(FOO, BAR);
        for (int i = 0; i < NAMES.length; i++) {
            tm.addRow().cell(FOO, NAMES[i]).cell(BAR, NUMBERS[i]);
        }
    }

    @Test
    public void tableStringSort() {
        initUnsortedTable();

        // sort by name
        tm.sort(FOO, SortDir.ASC);

        // verify results
        rows = tm.getRows();
        int nr = rows.length;
        assertEquals("row count", NAMES.length, nr);
        for (int i = 0; i < nr; i++) {
            assertEquals(UNEX_SORT + i, SORTED_NAMES[i], rows[i].get(FOO));
        }

        // now the other way
        tm.sort(FOO, SortDir.DESC);

        // verify results
        rows = tm.getRows();
        nr = rows.length;
        assertEquals("row count", NAMES.length, nr);
        for (int i = 0; i < nr; i++) {
            assertEquals(UNEX_SORT + i,
                         SORTED_NAMES[nr - 1 - i], rows[i].get(FOO));
        }
    }

    @Test
    public void tableNumberSort() {
        initUnsortedTable();

        // sort by number
        tm.sort(BAR, SortDir.ASC);

        // verify results
        rows = tm.getRows();
        int nr = rows.length;
        assertEquals("row count", NUMBERS.length, nr);
        for (int i = 0; i < nr; i++) {
            assertEquals(UNEX_SORT + i, SORTED_NUMBERS[i], rows[i].get(BAR));
        }

        // now the other way
        tm.sort(BAR, SortDir.DESC);

        // verify results
        rows = tm.getRows();
        nr = rows.length;
        assertEquals("row count", NUMBERS.length, nr);
        for (int i = 0; i < nr; i++) {
            assertEquals(UNEX_SORT + i,
                         SORTED_NUMBERS[nr - 1 - i], rows[i].get(BAR));
        }
    }

    @Test
    public void sortAndFormat() {
        initUnsortedTable();

        // set hex formatter
        tm.setFormatter(BAR, HexFormatter.INSTANCE);

        // sort by number
        tm.sort(BAR, SortDir.ASC);

        // verify results
        rows = tm.getRows();
        int nr = rows.length;
        assertEquals("row count", SORTED_HEX.length, nr);
        for (int i = 0; i < nr; i++) {
            assertEquals(UNEX_SORT + i, SORTED_HEX[i], rows[i].getAsString(BAR));
        }
    }

    private static final String[][] SORTED_NAMES_AND_HEX = {
            {ELEVEN, "0xb"},
            {FOUR, "0x4"},
            {ONE, "0x1"},
            {THIRTY, "0x1e"},
            {THREE, "0x3"},
            {TWELVE, "0xc"},
            {TWENTY, "0x14"},
            {TWO, "0x2"},
    };

    @Test
    public void sortAndFormatTwo() {
        initUnsortedTable();
        tm.setFormatter(BAR, HexFormatter.INSTANCE);
        tm.sort(FOO, SortDir.ASC);
        rows = tm.getRows();
        int nr = rows.length;
        for (int i = 0; i < nr; i++) {
            String[] exp = SORTED_NAMES_AND_HEX[i];
            String[] act = rows[i].getAsFormattedStrings();
            assertArrayEquals(UNEX_SORT + i, exp, act);
        }
    }

    private static final String[] FBZ = {FOO, BAR, ZOO};

    @Test
    public void getColumnIds() {
        tm = new TableModel(FOO, BAR, ZOO);
        assertArrayEquals("col IDs", FBZ, tm.getColumnIds());
    }

    @Test
    public void sortDirAsc() {
        assertEquals("asc sort dir", SortDir.ASC, TableModel.sortDir("asc"));
    }

    @Test
    public void sortDirDesc() {
        assertEquals("desc sort dir", SortDir.DESC, TableModel.sortDir("desc"));
    }

    @Test
    public void sortDirOther() {
        assertEquals("other sort dir", SortDir.ASC, TableModel.sortDir("other"));
    }

    @Test
    public void sortDirNull() {
        assertEquals("null sort dir", SortDir.ASC, TableModel.sortDir(null));
    }

    @Test
    public void enumSort() {
        tm = new TableModel(FOO);
        tm.addRow().cell(FOO, StarWars.HAN_SOLO);
        tm.addRow().cell(FOO, StarWars.C3PO);
        tm.addRow().cell(FOO, StarWars.JABBA_THE_HUTT);
        tm.addRow().cell(FOO, StarWars.LEIA_ORGANA);
        tm.addRow().cell(FOO, StarWars.R2D2);
        tm.addRow().cell(FOO, StarWars.LUKE_SKYWALKER);

        tm.sort(FOO, SortDir.ASC);

        // verify expected results
        StarWars[] ordered = StarWars.values();
        TableModel.Row[] rows = tm.getRows();
        assertEquals("wrong length?", ordered.length, rows.length);
        int nr = rows.length;
        for (int i = 0; i < nr; i++) {
            assertEquals(UNEX_SORT + i, ordered[i], rows[i].get(FOO));
        }
    }

    @Test
    public void stringAnnotation() {
        tm = new TableModel(FOO);
        tm.addAnnotation(BAR, ZOO);
        Collection<TableModel.Annot> annots = tm.getAnnotations();
        assertEquals("wrong size", 1, annots.size());

        TableModel.Annot annot = annots.iterator().next();
        assertEquals("wrong key", BAR, annot.key());
        assertEquals("wrong value", ZOO, annot.value());
    }

    private static final String K_INT = "int";
    private static final String K_BOOL = "bool";
    private static final String K_FLOAT = "float";
    private static final String K_DOUBLE = "double";
    private static final String K_ENUM = "enum";

    private TableModel.Annot getAnnotation(Collection<TableModel.Annot> annots, String key) {
        final TableModel.Annot[] annot = {null};
        annots.forEach(a -> {
            if (a.key().equals(key)) {
                annot[0] = a;
            }
        });
        return annot[0];
    }

    private void verifyCollectionContains(Collection<TableModel.Annot> annots,
                                          String key, int i) {
        TableModel.Annot a = getAnnotation(annots, key);
        assertEquals("wrong int value", i, a.value());
    }

    private void verifyCollectionContains(Collection<TableModel.Annot> annots,
                                          String key, boolean b) {
        TableModel.Annot a = getAnnotation(annots, key);
        assertEquals("wrong boolean value", b, a.value());
    }

    private void verifyCollectionContains(Collection<TableModel.Annot> annots,
                                          String key, float f) {
        TableModel.Annot a = getAnnotation(annots, key);
        assertEquals("wrong float value", f, a.value());
    }

    private void verifyCollectionContains(Collection<TableModel.Annot> annots,
                                          String key, double d) {
        TableModel.Annot a = getAnnotation(annots, key);
        assertEquals("wrong double value", d, a.value());
    }

    private void verifyCollectionContains(Collection<TableModel.Annot> annots,
                                          String key, Enum<?> e) {
        TableModel.Annot a = getAnnotation(annots, key);
        assertEquals("wrong double value", e, a.value());
    }

    @Test
    public void primitivesAnnotation() {
        tm = new TableModel(FOO);
        tm.addAnnotation(K_INT, 1);
        tm.addAnnotation(K_BOOL, true);
        tm.addAnnotation(K_FLOAT, 3.14f);
        tm.addAnnotation(K_DOUBLE, 2.71828);
        tm.addAnnotation(K_ENUM, StarWars.LUKE_SKYWALKER);

        Collection<TableModel.Annot> annots = tm.getAnnotations();
        assertEquals("wrong size", 5, annots.size());

        verifyCollectionContains(annots, K_INT, 1);
        verifyCollectionContains(annots, K_BOOL, true);
        verifyCollectionContains(annots, K_FLOAT, 3.14f);
        verifyCollectionContains(annots, K_DOUBLE, 2.71828);
        verifyCollectionContains(annots, K_ENUM, StarWars.LUKE_SKYWALKER);
    }

    // TODO: add support for compound object value
}
