/*
 * 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.topo;

import org.junit.BeforeClass;
import org.junit.Test;
import org.onosproject.ui.topo.PropertyPanel.Prop;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static org.junit.Assert.*;

/**
 * Unit tests for {@link PropertyPanel}.
 */
public class PropertyPanelTest {

    private static final String TITLE_ORIG = "Original Title";
    private static final String TYPE_ORIG = "Original type ID";
    private static final String TITLE_NEW = "New Title";
    private static final String TYPE_NEW = "New type";
    private static final String SOME_IDENTIFICATION = "It's Me!";

    private static final String KEY_A = "A";
    private static final String KEY_B = "B";
    private static final String KEY_C = "C";
    private static final String SEP = "-";
    private static final String KEY_Z = "Z";
    private static final String VALUE_A = "Hay";
    private static final String VALUE_B = "Bee";
    private static final String VALUE_C = "Sea";
    private static final String VALUE_Z = "Zed";
    private static final String GID_A = "gid-A";
    private static final String GID_B = "gid-B";
    private static final String GID_C = "gid-C";
    private static final String GID_Z = "gid-Z";
    private static final String TT_A = "toolTip-A";
    private static final String TT_B = "toolTip-B";
    private static final String TT_C = "toolTip-C";
    private static final String TT_Z = "toolTip-Z";

    private static final Map<String, Prop> PROP_MAP = new HashMap<>();

    private static class FooClass {
        private final String s;
        FooClass(String s) {
            this.s = s;
        }

        @Override
        public String toString() {
            return ">" + s + "<";
        }
    }

    private PropertyPanel pp;



    @BeforeClass
    public static void setUpClass() {
        PROP_MAP.put(KEY_A, new Prop(KEY_A, VALUE_A));
        PROP_MAP.put(KEY_B, new Prop(KEY_B, VALUE_B));
        PROP_MAP.put(KEY_C, new Prop(KEY_C, VALUE_C));
        PROP_MAP.put(KEY_Z, new Prop(KEY_Z, VALUE_Z));
        PROP_MAP.put(SEP, new PropertyPanel.Separator());
    }

    @Test
    public void basic() {
        pp = new PropertyPanel(TITLE_ORIG, TYPE_ORIG);
        assertEquals("wrong title", TITLE_ORIG, pp.title());
        assertEquals("wrong type", TYPE_ORIG, pp.typeId());
        assertNull("id?", pp.id());
        assertEquals("unexpected props", 0, pp.properties().size());
        assertEquals("unexpected buttons", 0, pp.buttons().size());
    }

    @Test
    public void changeTitle() {
        basic();
        pp.title(TITLE_NEW);
        assertEquals("wrong title", TITLE_NEW, pp.title());
    }

    @Test
    public void changeType() {
        basic();
        pp.typeId(TYPE_NEW);
        assertEquals("wrong type", TYPE_NEW, pp.typeId());
    }

    @Test
    public void setId() {
        basic();
        pp.id(SOME_IDENTIFICATION);
        assertEquals("wrong id", SOME_IDENTIFICATION, pp.id());
    }

    private void validateProps(String... keys) {
        Iterator<Prop> iter = pp.properties().iterator();
        for (String k: keys) {
            Prop exp = PROP_MAP.get(k);
            Prop act = iter.next();
            assertEquals("Bad prop sequence", exp, act);
        }
    }

    private void validateProp(String key, String expValue) {
        Iterator<Prop> iter = pp.properties().iterator();
        Prop prop = null;
        while (iter.hasNext()) {
            Prop p = iter.next();
            if (p.key().equals(key)) {
                prop = p;
                break;
            }
        }
        if (prop == null) {
            fail("no prop found with key: " + key);
        }
        assertEquals("Wrong prop value", expValue, prop.value());
    }

    @Test
    public void props() {
        basic();
        pp.addProp(KEY_A, VALUE_A)
            .addProp(KEY_B, VALUE_B)
            .addProp(KEY_C, VALUE_C);
        assertEquals("bad props", 3, pp.properties().size());
        validateProps(KEY_A, KEY_B, KEY_C);
    }

    @Test
    public void separator() {
        props();
        pp.addSeparator()
            .addProp(KEY_Z, VALUE_Z);

        assertEquals("bad props", 5, pp.properties().size());
        validateProps(KEY_A, KEY_B, KEY_C, SEP, KEY_Z);
    }

    @Test
    public void removeAllProps() {
        props();
        assertEquals("wrong props", 3, pp.properties().size());
        pp.removeAllProps();
        assertEquals("unexpected props", 0, pp.properties().size());
    }

    @Test
    public void adjustProps() {
        props();
        pp.removeProps(KEY_B, KEY_A);
        pp.addProp(KEY_Z, VALUE_Z);
        validateProps(KEY_C, KEY_Z);
    }

    @Test
    public void intValues() {
        basic();
        pp.addProp(KEY_A, 200)
          .addProp(KEY_B, 2000)
          .addProp(KEY_C, 1234567);

        validateProp(KEY_A, "200");
        validateProp(KEY_B, "2,000");
        validateProp(KEY_C, "1,234,567");
    }

    @Test
    public void longValues() {
        basic();
        pp.addProp(KEY_A, 200L)
          .addProp(KEY_B, 2000L)
          .addProp(KEY_C, 1234567L)
          .addProp(KEY_Z, Long.MAX_VALUE);

        validateProp(KEY_A, "200");
        validateProp(KEY_B, "2,000");
        validateProp(KEY_C, "1,234,567");
        validateProp(KEY_Z, "9,223,372,036,854,775,807");
    }

    @Test
    public void objectValue() {
        basic();
        pp.addProp(KEY_A, new FooClass("a"))
            .addProp(KEY_B, new FooClass("bxyyzy"), "[xz]");

        validateProp(KEY_A, ">a<");
        validateProp(KEY_B, ">byyy<");
    }

    private static final ButtonDescriptor BD_A =
            new ButtonDescriptor(KEY_A, GID_A, TT_A);
    private static final ButtonDescriptor BD_B =
            new ButtonDescriptor(KEY_B, GID_B, TT_B);
    private static final ButtonDescriptor BD_C =
            new ButtonDescriptor(KEY_C, GID_C, TT_C);
    private static final ButtonDescriptor BD_Z =
            new ButtonDescriptor(KEY_Z, GID_Z, TT_Z);

    private void verifyButtons(String... keys) {
        Iterator<ButtonDescriptor> iter = pp.buttons().iterator();
        for (String k: keys) {
            assertEquals("wrong button", k, iter.next().id());
        }
        assertFalse("too many buttons", iter.hasNext());
    }

    @Test
    public void buttons() {
        basic();
        pp.addButton(BD_A)
                .addButton(BD_B);
        assertEquals("wrong buttons", 2, pp.buttons().size());
        verifyButtons(KEY_A, KEY_B);

        pp.removeButtons(BD_B)
                .addButton(BD_C)
                .addButton(BD_Z);
        assertEquals("wrong buttons", 3, pp.buttons().size());
        verifyButtons(KEY_A, KEY_C, KEY_Z);

        pp.removeAllButtons()
                .addButton(BD_B);
        assertEquals("wrong buttons", 1, pp.buttons().size());
        verifyButtons(KEY_B);
    }
}
