/*
 * 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 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 ButtonId BD_A = new ButtonId(KEY_A);
    private static final ButtonId BD_B = new ButtonId(KEY_B);
    private static final ButtonId BD_C = new ButtonId(KEY_C);
    private static final ButtonId BD_Z = new ButtonId(KEY_Z);

    private void verifyButtons(String... keys) {
        Iterator<ButtonId> 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);
    }
}
