package com.atlassian.stash.internal.scm.git.command.config;

import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.util.Iterator;
import java.util.List;

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

public class ConfigOutputHandlerTest {

    @Test
    public void testProcessingOfConfigFile() throws Exception {
        Iterator<ConfigSection> iterator = process(IOUtils.toString(getClass().getResourceAsStream("config1.txt"))).iterator();
        checkRemoteDir(iterator.next(), "core", null, ImmutableMultimap.of("filemode", "true", "repositoryformatversion", "0", "bare", "false", "logallrefupdates", "true", "gitProxy", "ssh for kernel.org"));
        checkRemoteDir(iterator.next(), "remote", "origin", ImmutableMultimap.of("fetch", "+refs/heads/*:refs/remotes/origin/*", "url", "http://admin@host:7990/bitbucket/scm/TEST/test.git"));
        checkRemoteDir(iterator.next(), "branch", "master", ImmutableMultimap.of("remote", "origin", "merge", "refs/heads/master"));
        checkRemoteDir(iterator.next(), "stuff", null, ImmutableMultimap.of("escape", "value\\has\"quotes", "multi", "line value", "multi2", " line value # with comment "));
        assertFalse(iterator.hasNext());
    }

    @Test
    public void testProcessingOfInvalidConfigFile() {
        assertEquals(0, process("a=b\n").size());
    }

    @Test
    public void testProcessingOfConfigFileNoValue() {
        String config = "[submodule \"not_important\"]\n        a=";
        List<ConfigSection> configSections = process(config);
        assertEquals(1, configSections.size());
        assertEquals(ImmutableMultimap.of("a", ""), configSections.get(0).getEntries());
    }

    @Test
    public void testProcessingOfConfigFileNoValueComments() {
        String config = "[submodule \"not_important\"]\n        a= ; hahaha no value!";
        List<ConfigSection> configSections = process(config);
        assertEquals(1, configSections.size());
        assertEquals(ImmutableMultimap.of("a", ""), configSections.get(0).getEntries());
    }

    @Test
    public void testProcessingOfConfigFileSubSections() {
        String config = "[s-ub.sub-module \"not_important\"]\n        a=b ; hahaha no value!";
        List<ConfigSection> configSections = process(config);
        assertEquals(1, configSections.size());
        assertEquals(ImmutableMultimap.of("a", "b"), configSections.get(0).getEntries());
    }

    @Test
    public void testProcessingOfConfigFileNoEqualsInvalid() {
        String config = "[submodule \"not_important\"]\n        a ; hahaha no value!";
        List<ConfigSection> configSections = process(config);
        assertEquals(1, configSections.size());
        assertEquals(ImmutableMultimap.<String, String>of(), configSections.get(0).getEntries());
    }

    @Test
    public void testProcessingOfConfigFileNoEqualsValid() {
        String config = "[submodule \"not_important\"]\n        a";
        List<ConfigSection> configSections = process(config);
        assertEquals(1, configSections.size());
        assertEquals(ImmutableMultimap.of("a", "true"), configSections.get(0).getEntries());
    }

    @Test
    public void testProcessingOfConfigFileMixedEolStyles() {
        String config = "[core]\r\n" +
                "\tsetting1 = value1\n" +
                "\tsetting2 = value2\r" +
                "\tsetting3 = value3\n" +
                "\tsetting4 = value4\r\n" +
                "\tsetting5 = value5\r";

        List<ConfigSection> configSections = process(config);
        assertEquals(1, configSections.size());
        assertEquals("core", configSections.get(0).getName());
        assertEquals(ImmutableMultimap.of("setting1", "value1", "setting2", "value2", "setting3", "value3", "setting4", "value4", "setting5", "value5"), configSections.get(0).getEntries());
    }

    private List<ConfigSection> process(String configString) {
        ConfigOutputHandler handler = new ConfigOutputHandler();
        try {
            handler.process(new ByteArrayInputStream(configString.getBytes("ASCII")));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return handler.getSections();
    }

    private void checkRemoteDir(ConfigSection section, String path, String subsection,
                                Multimap<String, String> entries) {
        assertEquals(path, section.getName());
        assertEquals(subsection, section.getSubsection());
        assertEquals(entries, section.getEntries());
    }
}
