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

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicReference;

import junit.framework.TestCase;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IArgumentMatcher;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;

/**
 * Tests for ConfigInstaller
 */
public class ConfigInstallerTest extends TestCase {

    BundleContext mockBundleContext;
    Bundle mockBundle;
    ConfigurationAdmin mockConfigurationAdmin;
    Configuration mockConfiguration;

    protected void setUp() throws Exception
    {
        super.setUp();
        mockBundleContext = EasyMock.createMock(BundleContext.class);
        mockBundle = EasyMock.createMock(Bundle.class);
        mockConfigurationAdmin = EasyMock.createMock(ConfigurationAdmin.class);
        mockConfiguration = EasyMock.createMock(Configuration.class);
    }


    public void testParsePidWithoutFactoryPid()
    {
        ConfigInstaller ci = new ConfigInstaller(null, null, null);

        String path = "pid.cfg";
        assertEquals( "Pid without Factory Pid calculated", "pid", ci.parsePid( path )[0] );
        assertEquals( "Pid without Factory Pid calculated", null, ci.parsePid( path )[1] );
    }


    public void testParsePidWithFactoryPid()
    {
        ConfigInstaller ci = new ConfigInstaller(null, null, null);

        String path = "factory-pid.cfg";
        assertEquals( "Pid with Factory Pid calculated", "factory", ci.parsePid( path )[0] );
        assertEquals( "Pid with Factory Pid calculated", "pid", ci.parsePid( path )[1] );
    }

    public void testTypedConfiguration() throws Exception
    {
        File file = File.createTempFile("test", ".config");
        try (OutputStream os = new FileOutputStream(file)) {
            os.write("networkInterface=\"wlp3s0\"\n".getBytes("UTF-8"));
        }
        String pid = file.getName().substring(0, file.getName().indexOf(".config"));

        Capture<Dictionary<String, Object>> props = new Capture<>();
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(mockConfiguration);
        EasyMock.expect(mockConfiguration.getProperties())
                .andReturn(null);
        EasyMock.expect(mockBundleContext.getProperty((String) EasyMock.anyObject()))
                .andReturn(null)
                .anyTimes();
        EasyMock.expect(mockBundleContext.getBundle())
                .andReturn(mockBundle);
        mockConfiguration.update(EasyMock.capture(props));
        EasyMock.expectLastCall();
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );
        ci.install(file);

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
        Dictionary<String, Object> loaded = props.getValue();
        assertNotNull(loaded);
        assertEquals("wlp3s0", loaded.get("networkInterface"));
    }

    public void testTypedConfigurationFloat() throws Exception
    {
        File file = File.createTempFile("test", ".config");
        try (OutputStream os = new FileOutputStream(file)) {
            os.write("key=F\"1137191584\"\n".getBytes("UTF-8"));
        }
        String pid = file.getName().substring(0, file.getName().indexOf(".config"));

        Capture<Dictionary<String, Object>> props = new Capture<>();
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(mockConfiguration);
        EasyMock.expect(mockConfiguration.getProperties())
                .andReturn(null);
        EasyMock.expect(mockBundleContext.getProperty((String) EasyMock.anyObject()))
                .andReturn(null)
                .anyTimes();
        EasyMock.expect(mockBundleContext.getBundle())
                .andReturn(mockBundle);
        mockConfiguration.update(EasyMock.capture(props));
        EasyMock.expectLastCall();
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );
        ci.install(file);

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
        Dictionary<String, Object> loaded = props.getValue();
        assertNotNull(loaded);
        assertEquals(400.333F, loaded.get("key"));
    }

    public void testGetNewFactoryConfiguration() throws Exception
    {
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                    .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.createFactoryConfiguration( "pid", "?" ))
                    .andReturn(mockConfiguration);
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        assertEquals( "Factory configuration retrieved", mockConfiguration, ci.getConfiguration( "pid-factoryPid.cfg", "pid", "factoryPid" ) );

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
    }


    public void testGetExistentFactoryConfiguration() throws Exception
    {
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                        .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.createFactoryConfiguration( "pid", "?" ))
                        .andReturn(mockConfiguration);
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        assertEquals( "Factory configuration retrieved", mockConfiguration, ci.getConfiguration( "pid-factoryPid.cfg","pid", "factoryPid" ) );

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
    }


    public void testGetExistentNoFactoryConfiguration() throws Exception
    {
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                        .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration( "pid", "?" ))
                        .andReturn(mockConfiguration);
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        assertEquals( "Factory configuration retrieved", mockConfiguration, ci.getConfiguration( "pid.cfg", "pid", null ) );

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
    }


    public void testDeleteConfig() throws Exception
    {
        mockConfiguration.delete();
        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.LOG_LEVEL)).andReturn(null);
        EasyMock.expect(mockBundleContext.getBundle()).andReturn(mockBundle).anyTimes();
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                        .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration("pid", "?" ))
                        .andReturn(mockConfiguration);
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        assertTrue( ci.deleteConfig( new File( "pid.cfg" ) ) );

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
    }

    public void testCreateConfigAndObserveCMDeleted() throws Exception
    {
        File file = File.createTempFile("test", ".config");
        try (OutputStream os = new FileOutputStream(file)) {
            os.write("key=F\"1137191584\"\n".getBytes("UTF-8"));
        }
        String pid = file.getName().substring(0, file.getName().indexOf(".config"));

        final Capture<Dictionary<String, Object>> props = new Capture<>();

        EasyMock.expect(mockConfiguration.getProperties())
                .andReturn(null);
        EasyMock.expect(mockBundleContext.getProperty((String) EasyMock.anyObject()))
                .andReturn(null)
                .anyTimes();
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(mockConfiguration);

        ServiceReference<ConfigurationAdmin> sr = EasyMock.createMock(ServiceReference.class);
        mockConfiguration.update(EasyMock.capture(props));
        EasyMock.expectLastCall();

        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(mockConfiguration);
        EasyMock.expect(mockConfiguration.getProperties())
                .andAnswer(new IAnswer<Dictionary<String, Object>>() {
                    @Override
                    public Dictionary<String, Object> answer() throws Throwable {
                        return props.getValue();
                    }
                });
        EasyMock.expect(mockConfiguration.getPid())
                .andReturn(pid);

        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext, sr);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );
        ci.install(file);

        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_UPDATED, null, pid ) );

        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_DELETED, null, pid ) );

        assertFalse("Configuration file should be deleted", file.isFile());
    }

    public void testUseExistingConfigAndObserveCMDeleted() throws Exception
    {
        String pid = "test";

        Capture<Dictionary<String, Object>> props = new Capture<>();

        EasyMock.expect(mockConfiguration.getProperties())
                .andReturn(null);
        EasyMock.expect(mockBundleContext.getProperty((String) EasyMock.anyObject()))
                .andReturn(null)
                .anyTimes();
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(mockConfiguration);

        ServiceReference<ConfigurationAdmin> sr = EasyMock.createMock(ServiceReference.class);
        mockConfiguration.update(EasyMock.capture(props));
        EasyMock.expectLastCall();

        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext, sr);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_UPDATED, null, pid ) );
        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_DELETED, null, pid ) );
    }

    public void testUseExistingConfigWithFileinstallFilenameAndObserveCMDeleted() throws Exception
    {
        File file = File.createTempFile("test", ".config");
        try (OutputStream os = new FileOutputStream(file)) {
            os.write("key=F\"1137191584\"\n".getBytes("UTF-8"));
        }
        String pid = "test";

        Capture<Dictionary<String, Object>> propsCapture = new Capture<>();
        Dictionary<String, Object> props = new Hashtable<>();
        props.put(DirectoryWatcher.FILENAME, file.toURI().toString());

        EasyMock.expect(mockConfiguration.getProperties())
                .andReturn(props);
        EasyMock.expect(mockBundleContext.getProperty((String) EasyMock.anyObject()))
                .andReturn(null)
                .anyTimes();
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(mockConfiguration);
        EasyMock.expect(mockConfiguration.getPid())
                .andReturn(pid);

        ServiceReference<ConfigurationAdmin> sr = EasyMock.createMock(ServiceReference.class);
        mockConfiguration.update(EasyMock.capture(propsCapture));
        EasyMock.expectLastCall();

        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext, sr);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_UPDATED, null, pid ) );
        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_DELETED, null, pid ) );

        assertFalse("Configuration file should be deleted", file.isFile());
    }

    public void testDoConfigurationEventSavesUpdatedConfigurationWhenUsingCachingPersistence() throws Exception
    {
        final File file = File.createTempFile("test", ".config");
        try (OutputStream os = new FileOutputStream(file)) {
            os.write("networkInterface = \"wlp3s1\"\n".getBytes("UTF-8"));
        }

        String pid = file.getName().substring(0, file.getName().indexOf(".config"));

        ServiceReference<ConfigurationAdmin> sr = EasyMock.createMock(ServiceReference.class);

        EasyMock.expect(mockBundleContext.getProperty((String) EasyMock.anyObject()))
                .andReturn(null)
                .anyTimes();

        final Configuration cachingPersistenceConfiguration = EasyMock.createMock(Configuration.class);

        final Dictionary<String, Object> cachedProps = new Hashtable<String, Object>() {
            {
                put("networkInterface", "wlp3s0");
                put(DirectoryWatcher.FILENAME, file.toURI().toString());
            }
        };

        EasyMock.expect(cachingPersistenceConfiguration.getProperties())
                .andReturn(cachedProps)
                .anyTimes();

        EasyMock.expect(cachingPersistenceConfiguration.getPid())
                .andReturn(pid);

        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, "?"))
                .andReturn(cachingPersistenceConfiguration)
                .anyTimes();

        EasyMock.expect(mockConfigurationAdmin.getConfiguration(pid, null))
                .andReturn(cachingPersistenceConfiguration)
                .anyTimes();

        final Configuration newConfiguration = EasyMock.createMock(Configuration.class);

        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                .andReturn(new Configuration[] { newConfiguration });

        EasyMock.expect(newConfiguration.getProperties())
                .andReturn(null);

        EasyMock.expect(newConfiguration.getPid())
                .andReturn(pid);

        final Capture<Dictionary<String, Object>> props = new Capture<>();
        newConfiguration.update(EasyMock.capture(props));

        cachingPersistenceConfiguration.update(EasyMock.capture(props));
        EasyMock.expectLastCall()
                .andAnswer(new IAnswer<Object>() {
                    @Override
                    public Object answer() throws Throwable {

                        cachedProps.put("networkInterface", props.getValue().get("networkInterface"));

                        return null;
                   }
               }).anyTimes();

        EasyMock.replay(mockBundleContext, mockConfigurationAdmin, cachingPersistenceConfiguration, newConfiguration, sr);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        ci.install(file);

        Dictionary<String, Object> loaded = props.getValue();
        assertNotNull(loaded);
        assertEquals("wlp3s1", loaded.get("networkInterface"));

        ci.doConfigurationEvent( new ConfigurationEvent(sr , ConfigurationEvent.CM_UPDATED, null, pid ) );

        assertEquals("networkInterface = \"wlp3s1\"", Files.readAllLines( Paths.get(file.toURI()) ).get(0));
    }

    public void testSetConfiguration() throws Exception
    {
        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.CONFIG_ENCODING)).andReturn(null);
        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.LOG_DEFAULT)).andReturn(null);
        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.LOG_LEVEL)).andReturn(null);
        EasyMock.expect(mockBundleContext.getBundle()).andReturn(mockBundle).anyTimes();
        EasyMock.expect(mockConfiguration.getProperties()).andReturn(new Hashtable<String, Object>());
        EasyMock.reportMatcher(new IArgumentMatcher()
        {
            public boolean matches( Object argument )
            {
                return ((Dictionary) argument).get("testkey").equals("testvalue");
            }

            public void appendTo(StringBuffer buffer)
            {
                buffer.append("<Dictionary check: testkey present?>");
            }
        } );
        mockConfiguration.update(new Hashtable<String, Object>());
        EasyMock.expect(mockConfigurationAdmin.listConfigurations((String) EasyMock.anyObject()))
                        .andReturn(null);
        EasyMock.expect(mockConfigurationAdmin.getConfiguration("firstcfg", "?"))
                        .andReturn(mockConfiguration);
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        assertTrue( ci.setConfig( new File( "src/test/resources/watched/firstcfg.cfg" ) ) );

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
    }
    
    public void testShouldSaveConfig() 
    {
        final AtomicReference<Boolean> disable = new AtomicReference<Boolean>();
        final AtomicReference<Boolean> enable = new AtomicReference<Boolean>();
        
        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.DISABLE_CONFIG_SAVE)).andAnswer(
                new IAnswer<String>() {
                    public String answer() throws Throwable {
                        return disable.get() != null ? disable.get().toString() : null;
                    }
                }
        ).anyTimes();
        EasyMock.expect(mockBundleContext.getProperty(DirectoryWatcher.ENABLE_CONFIG_SAVE)).andAnswer(
                new IAnswer<String>() {
                    public String answer() throws Throwable {
                        return enable.get() != null ? enable.get().toString() : null;
                    }
                }
        ).anyTimes();
        EasyMock.replay(mockConfiguration, mockConfigurationAdmin, mockBundleContext);

        ConfigInstaller ci = new ConfigInstaller( mockBundleContext, mockConfigurationAdmin, new FileInstall() );

        disable.set(null);
        enable.set(null);
        assertTrue( ci.shouldSaveConfig() );

        disable.set(Boolean.FALSE);
        enable.set(null);
        assertFalse( ci.shouldSaveConfig() );

        disable.set(Boolean.TRUE);
        enable.set(null);
        assertTrue( ci.shouldSaveConfig() );

        disable.set(null);
        enable.set(Boolean.FALSE);
        assertFalse( ci.shouldSaveConfig() );

        disable.set(Boolean.FALSE);
        enable.set(Boolean.FALSE);
        assertFalse( ci.shouldSaveConfig() );

        disable.set(Boolean.TRUE);
        enable.set(Boolean.FALSE);
        assertFalse( ci.shouldSaveConfig() );

        disable.set(null);
        enable.set(Boolean.TRUE);
        assertTrue( ci.shouldSaveConfig() );

        disable.set(Boolean.FALSE);
        enable.set(Boolean.TRUE);
        assertTrue( ci.shouldSaveConfig() );

        disable.set(Boolean.TRUE);
        enable.set(Boolean.TRUE);
        assertTrue( ci.shouldSaveConfig() );

        EasyMock.verify(mockConfiguration, mockConfigurationAdmin, mockBundleContext);
    }

}
