/*
 * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.controller.netconf.confignetconfconnector.osgi;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.junit.Assert;
import org.junit.Test;
import org.junit.matchers.JUnitMatchers;
import org.opendaylight.controller.config.api.LookupRegistry;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.yangtools.yang.common.QName;

import java.net.URI;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

public class NetconfOperationServiceImplTest {

    private Date date = new Date(0);

    @Test
    public void testCheckConsistencyBetweenYangStoreAndConfig_ok() throws Exception {
        NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(
                mockJmxClient("qname1", "qname2"),
                mockYangStoreSnapshot("qname2", "qname1"));
    }

    @Test
    public void testCheckConsistencyBetweenYangStoreAndConfig_ok2() throws Exception {
        NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(
                mockJmxClient("qname1", "qname2", "qname4", "qname5"),
                mockYangStoreSnapshot("qname2", "qname1"));
    }

    @Test
    public void testCheckConsistencyBetweenYangStoreAndConfig_ok3() throws Exception {
        NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(
                mockJmxClient(),
                mockYangStoreSnapshot());
    }

    @Test(expected = IllegalStateException.class)
    public void testCheckConsistencyBetweenYangStoreAndConfig_yangStoreMore() throws Exception {
        try {
            NetconfOperationServiceImpl.checkConsistencyBetweenYangStoreAndConfig(mockJmxClient("qname1"),
                    mockYangStoreSnapshot("qname2", "qname1"));
        } catch (IllegalStateException e) {
            String message = e.getMessage();
            Assert.assertThat(
                    message,
                    JUnitMatchers
                            .containsString(" missing from config subsystem but present in yangstore: [(namespace?revision=1970-01-01)qname2]"));
            Assert.assertThat(
                    message,
                    JUnitMatchers
                            .containsString("All modules present in config: [(namespace?revision=1970-01-01)qname1]"));
            throw e;
        }
    }

    private YangStoreSnapshot mockYangStoreSnapshot(String... qnames) {
        YangStoreSnapshot mock = mock(YangStoreSnapshot.class);

        Map<String, Map<String, ModuleMXBeanEntry>> map = Maps.newHashMap();

        Map<String, ModuleMXBeanEntry> innerMap = Maps.newHashMap();

        int i = 1;
        for (String qname : qnames) {
            innerMap.put(Integer.toString(i++), mockMBeanEntry(qname));
        }

        map.put("1", innerMap);

        doReturn(map).when(mock).getModuleMXBeanEntryMap();

        return mock;
    }

    private ModuleMXBeanEntry mockMBeanEntry(String qname) {
        ModuleMXBeanEntry mock = mock(ModuleMXBeanEntry.class);
        QName q = getQName(qname);
        doReturn(q).when(mock).getYangModuleQName();
        return mock;
    }

    private QName getQName(String qname) {
        return new QName(URI.create("namespace"), date, qname);
    }

    private LookupRegistry mockJmxClient(String... visibleQNames) {
        LookupRegistry mock = mock(LookupRegistry.class);
        Set<String> qnames = Sets.newHashSet();
        for (String visibleQName : visibleQNames) {
            QName q = getQName(visibleQName);
            qnames.add(q.toString());
        }
        doReturn(qnames).when(mock).getAvailableModuleFactoryQNames();
        return mock;
    }
}

@@ -834,16 +834,84 @@
 et.URI;%0A
+import java.text.ParseException;%0Aimport java.text.SimpleDateFormat;%0A
 import j
@@ -925,16 +925,16 @@
 l.Date;%0A
-
 import j
@@ -970,16 +970,53 @@
 l.Set;%0A%0A
+import static org.junit.Assert.fail;%0A
 import s
@@ -1156,32 +1156,255 @@
 ate 
-Date date = new Date(0);
+static final Date date1970_01_01;%0A%0A    static %7B%0A        try %7B%0A            date1970_01_01 = new SimpleDateFormat(%22yyyy-MM-dd%22).parse(%221970-01-01%22);%0A        %7D catch (ParseException e) %7B%0A            throw new IllegalStateException(e);%0A        %7D%0A    %7D
 %0A%0A  
@@ -2279,48 +2279,8 @@
 Test
-(expected = IllegalStateException.class)
 %0A   
@@ -2554,24 +2554,118 @@
 %22qname1%22));%0A
+            fail(%22An exception of type %22 + IllegalArgumentException.class + %22 was expected%22);%0A
         %7D ca
@@ -2880,17 +2880,16 @@
 String(%22
- 
 missing 
@@ -3198,29 +3198,8 @@
 ));%0A
-            throw e;%0A
     
@@ -4034,32 +4034,32 @@
 String qname) %7B%0A
-
         return n
@@ -4096,16 +4096,26 @@
 %22), date
+1970_01_01
 , qname)

Fix date initialization in NetconfOperationServiceImplTest.