/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.felix.configurator.impl;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Vector;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;

public class ConfiguratorTest {

    private Configurator configurator;

    private BundleContext bundleContext;

    private Bundle bundle;

    private ConfigurationAdmin configurationAdmin;

    private ServiceReference<ConfigurationAdmin> caRef;

    @SuppressWarnings("unchecked")
    @Before public void setup() throws IOException {
        bundle = mock(Bundle.class);
        when(bundle.getBundleId()).thenReturn(42L);
        when(bundle.getState()).thenReturn(Bundle.ACTIVE);
        bundleContext = mock(BundleContext.class);
        when(bundle.getBundleContext()).thenReturn(bundleContext);
        when(bundleContext.getBundle()).thenReturn(bundle);
        when(bundleContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION)).thenReturn(bundle);
        when(bundleContext.getBundle(42)).thenReturn(bundle);
        when(bundleContext.getBundles()).thenReturn(new Bundle[0]);
        when(bundleContext.getDataFile("binaries" + File.separatorChar + ".check")).thenReturn(Files.createTempDirectory("test").toFile());
        caRef = mock(ServiceReference.class);
        when(caRef.getBundle()).thenReturn(bundle);

        configurationAdmin = mock(ConfigurationAdmin.class);
        when(bundleContext.getService(caRef)).thenReturn(configurationAdmin);

        configurator = new Configurator(bundleContext, Collections.singletonList(caRef));
    }

    private Bundle setupBundle(final long id) throws Exception {
        return setupBundle(id, String.valueOf(id));
    }

    private long lastModified = 1;

    private Bundle setupBundle(final long id, final String jsonName) throws Exception {
        final Bundle b = mock(Bundle.class);
        when(b.getBundleId()).thenReturn(id);
        when(b.getLastModified()).thenReturn(lastModified);
        lastModified++;
        when(b.getState()).thenReturn(Bundle.ACTIVE);
        final BundleWiring wiring = mock(BundleWiring.class);
        when(b.adapt(BundleWiring.class)).thenReturn(wiring);
        final BundleRequirement req = mock(BundleRequirement.class);
        when(wiring.getRequirements(Util.NS_OSGI_EXTENDER)).thenReturn(Collections.singletonList(req));
        final BundleWire wire = mock(BundleWire.class);
        when(wire.getProviderWiring()).thenReturn(wiring);
        when(wire.getRequirement()).thenReturn(req);
        when(wiring.getBundle()).thenReturn(bundle);
        when(wiring.getRequiredWires(Util.NS_OSGI_EXTENDER)).thenReturn(Collections.singletonList(wire));
        final Vector<URL> urls = new Vector<>();
        urls.add(this.getClass().getResource("/bundles/" + jsonName + ".json"));
        when(b.findEntries("OSGI-INF/configurator", "*.json", false)).thenReturn(urls.elements());

        final BundleContext bContext = mock(BundleContext.class);
        when(b.getBundleContext()).thenReturn(bContext);
        when(bContext.getServiceReferences(ConfigurationAdmin.class, null)).thenReturn(Collections.singleton(caRef));
        when(bundleContext.getBundle(id)).thenReturn(b);
        return b;
    }

    @Test public void testSimpleAddRemove() throws Exception {
        final Bundle b = setupBundle(1);

        Configuration c1 = mock(Configuration.class);
        Configuration c2 = mock(Configuration.class);
        when(configurationAdmin.getConfiguration("a", "?")).thenReturn(c1);
        when(configurationAdmin.getConfiguration("b", "?")).thenReturn(c2);

        when(c1.getChangeCount()).thenReturn(1L);
        when(c2.getChangeCount()).thenReturn(1L);
        configurator.processAddBundle(b);

        configurator.process();

        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=a)")).thenReturn(new Configuration[] {c1});
        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=b)")).thenReturn(new Configuration[] {c2});

        final Dictionary<String, Object> props1 = new Hashtable<>();
        props1.put("foo", "bar");
        verify(c1).updateIfDifferent(props1);
        final Dictionary<String, Object> props2 = new Hashtable<>();
        props2.put("x", "y");
        verify(c2).updateIfDifferent(props2);

        configurator.processRemoveBundle(1);
        configurator.process();

        verify(c1).delete();
        verify(c2).delete();
    }

    @Test public void testSimpleAddUpdate() throws Exception {
        final Bundle bV1 = setupBundle(2);
        final Bundle bV2 = setupBundle(2, "2a");

        // initial - no configuration
        Configuration c1 = mock(Configuration.class);
        Configuration c2 = mock(Configuration.class);
        Configuration c3 = mock(Configuration.class);
        when(c1.getChangeCount()).thenReturn(1L);
        when(c2.getChangeCount()).thenReturn(1L);
        when(c3.getChangeCount()).thenReturn(1L);
        when(configurationAdmin.getConfiguration("a", "?")).thenReturn(c1);
        when(configurationAdmin.getConfiguration("b", "?")).thenReturn(c2);
        when(configurationAdmin.getConfiguration("c", "?")).thenReturn(c3);

        configurator.processAddBundle(bV1);
        configurator.process();

        final Dictionary<String, Object> props1a = new Hashtable<>();
        props1a.put("foo", "bar2");
        final Dictionary<String, Object> props1b = new Hashtable<>();
        props1b.put("x", "y2");
        final Dictionary<String, Object> props1c = new Hashtable<>();
        props1c.put("c", "1");

        InOrder inorder = inOrder(c1,c2,c3);
        inorder.verify(c1).updateIfDifferent(props1a);
        inorder.verify(c1).getChangeCount();
        inorder.verify(c2).updateIfDifferent(props1b);
        inorder.verify(c2).getChangeCount();
        inorder.verify(c3).updateIfDifferent(props1c);
        inorder.verify(c3).getChangeCount();
        inorder.verifyNoMoreInteractions();

        // c1 and c2 are changed manually -> increase change count, c3 is not changed manually
        when(c1.getChangeCount()).thenReturn(2L);
        when(c2.getChangeCount()).thenReturn(2L);
        when(configurationAdmin.listConfigurations("(service.pid=a)")).thenReturn(new Configuration[] {c1});
        when(configurationAdmin.listConfigurations("(service.pid=b)")).thenReturn(new Configuration[] {c2});
        when(configurationAdmin.listConfigurations("(service.pid=c)")).thenReturn(new Configuration[] {c3});

        configurator.processAddBundle(bV2);
        configurator.process();

        final Dictionary<String, Object> props2a = new Hashtable<>();
        props2a.put("foo", "bar3");
        final Dictionary<String, Object> props2c = new Hashtable<>();
        props2c.put("c", "2");

        inorder = inOrder(c1, c2, c3);
        inorder.verify(c1).updateIfDifferent(props2a);
        inorder.verify(c1).getChangeCount();
        inorder.verify(c2).getChangeCount();
        inorder.verify(c3).updateIfDifferent(props2c);
        inorder.verify(c3).getChangeCount();
        inorder.verifyNoMoreInteractions();
    }

    @Test public void testSimpleRankingRemove() throws Exception {
        final Bundle b1 = setupBundle(1);
        final Bundle b2 = setupBundle(2);

        Configuration c1 = mock(Configuration.class);
        Configuration c2 = mock(Configuration.class);
        Configuration c3 = mock(Configuration.class);
        when(configurationAdmin.getConfiguration("a", "?")).thenReturn(c1);
        when(configurationAdmin.getConfiguration("b", "?")).thenReturn(c2);
        when(configurationAdmin.getConfiguration("c", "?")).thenReturn(c3);

        when(c1.getChangeCount()).thenReturn(1L);
        when(c2.getChangeCount()).thenReturn(1L);
        when(c3.getChangeCount()).thenReturn(1L);
        configurator.processAddBundle(b2);
        configurator.process();

        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=a)")).thenReturn(new Configuration[] {c1});
        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=b)")).thenReturn(new Configuration[] {c2});
        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=c)")).thenReturn(new Configuration[] {c3});

        final Dictionary<String, Object> props1 = new Hashtable<>();
        props1.put("foo", "bar2");
        final Dictionary<String, Object> props2 = new Hashtable<>();
        props2.put("x", "y2");

        configurator.processAddBundle(b1);
        configurator.process();

        final Dictionary<String, Object> props3 = new Hashtable<>();
        props3.put("foo", "bar");
        final Dictionary<String, Object> props4 = new Hashtable<>();
        props4.put("x", "y");

        configurator.processRemoveBundle(1);
        configurator.process();

        configurator.processRemoveBundle(2);
        configurator.process();

        InOrder inorder = inOrder(c1, c2);
        inorder.verify(c1).updateIfDifferent(props1);
        inorder.verify(c2).updateIfDifferent(props2);
        inorder.verify(c1).updateIfDifferent(props3);
        inorder.verify(c2).updateIfDifferent(props4);
        inorder.verify(c1).updateIfDifferent(props1);
        inorder.verify(c2).updateIfDifferent(props2);
        inorder.verify(c1).delete();
        inorder.verify(c2).delete();
        inorder.verifyNoMoreInteractions();
    }
}
