/*
 * 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.text.NumberFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

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

    // Modified property panel subclass to use ENGLISH locale formatter so
    //  we know formatted numbers will use comma for the thousand separator.
    private static final class EnglishPropertyPanel extends PropertyPanel {
        private static final NumberFormat ENGLISH_FORMATTER =
                NumberFormat.getInstance(Locale.ENGLISH);

        public EnglishPropertyPanel(String title, String typeId) {
            super(title, typeId);
        }

        @Override
        protected NumberFormat formatter() {
            return ENGLISH_FORMATTER;
        }
    }

    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 EnglishPropertyPanel(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);
    }
}
