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

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import junit.framework.Assert;

import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
import org.apache.ivy.core.event.EventManager;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.resolve.ResolveEngine;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.core.sort.SortEngine;
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorWriter;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.resolver.FileSystemResolver;
import org.apache.ivy.util.FileUtil;

public class TestHelper {

    public static DefaultArtifact newArtifact(String organisation, String module, String revision,
            String artifact, String type, String ext) {
        return new DefaultArtifact(ModuleRevisionId.newInstance(organisation, module, revision),
                new Date(), artifact, type, ext);
    }

    public static File getArchiveFileInCache(Ivy ivy, String mrid, String artifactName,
            String type, String ext) {
        DefaultArtifact artifact = new DefaultArtifact(ModuleRevisionId.parse(mrid), new Date(),
                artifactName, type, ext);
        return getRepositoryCacheManager(ivy, artifact.getModuleRevisionId())
                .getArchiveFileInCache(artifact);
    }

    public static File getArchiveFileInCache(Ivy ivy, String organisation, String module,
            String revision, String artifactName, String type, String ext) {
        DefaultArtifact artifact = newArtifact(organisation, module, revision, artifactName, type,
            ext);
        return getRepositoryCacheManager(ivy, artifact.getModuleRevisionId())
                .getArchiveFileInCache(artifact);
    }

    public static DefaultRepositoryCacheManager getRepositoryCacheManager(Ivy ivy,
            ModuleRevisionId id) {
        // WARN: this doesn't work if the resolver registered is a compound resolver (chain or dual)
        // and a sub resolver doesn't use the same cache manager as the parent
        return (DefaultRepositoryCacheManager) ivy.getSettings().getResolver(id)
                .getRepositoryCacheManager();
    }

    /**
     * Assertion utility methods to test if a collection of {@link ModuleRevisionId} matches a given
     * expected set of mrids.
     * <p>
     * Expected mrids is given as a String of comma separated string representations of
     * {@link ModuleRevisionId}.
     * 
     * @param expectedMrids
     *            the expected set of mrids
     * @param mrids
     *            the3 mrids to test
     */
    public static void assertModuleRevisionIds(String expectedMrids,
            Collection/* <ModuleRevisionId> */mrids) {
        Collection expected = parseMrids(expectedMrids);
        Assert.assertEquals(expected, mrids);
    }

    /**
     * Returns a Set of {@link ModuleRevisionId} corresponding to the given comma separated list of
     * their text representation.
     * 
     * @param mrids
     *            the text representation of the {@link ModuleRevisionId}
     * @return a collection of {@link ModuleRevisionId}
     */
    public static Collection parseMrids(String mrids) {
        String[] m = mrids.split(",?\\s+");
        Collection c = new LinkedHashSet();
        for (int i = 0; i < m.length; i++) {
            c.add(ModuleRevisionId.parse(m[i]));
        }
        return c;
    }

    /**
     * Returns an array of {@link ModuleRevisionId} corresponding to the given comma separated list
     * of their text representation.
     * 
     * @param mrids
     *            the text representation of the {@link ModuleRevisionId}
     * @return an array of {@link ModuleRevisionId}
     */
    public static ModuleRevisionId[] parseMridsToArray(String mrids) {
        Collection parsedMrids = parseMrids(mrids);
        return (ModuleRevisionId[]) parsedMrids.toArray(new ModuleRevisionId[parsedMrids.size()]);
    }

    /**
     * Parses a string represenation of a module descriptor in micro ivy format.
     * <p>
     * Examples:
     * 
     * <pre>
     * #A;1
     * </pre>
     * 
     * <hr/>
     * 
     * <pre>
     * #A;2-> #B;[1.0,1.5]
     * </pre>
     * 
     * <hr/>
     * 
     * <pre>
     * #A;3-> { #B;[1.0,1.5] #C;[2.0,2.5] }
     * </pre>
     * 
     * </p>
     * 
     * @param microIvy
     *            the micro ivy description of the module descriptor
     * @return the parsed module descriptor
     */
    public static ModuleDescriptor parseMicroIvyDescriptor(String microIvy) {
        Pattern mridPattern = ModuleRevisionId.NON_CAPTURING_PATTERN;
        Matcher m = mridPattern.matcher(microIvy);
        if (m.matches()) {
            return DefaultModuleDescriptor.newBasicInstance(ModuleRevisionId.parse(microIvy),
                new Date());
        }

        Pattern oneDependencyPattern = Pattern.compile("(" + mridPattern.pattern() + ")\\s*->\\s*("
                + mridPattern.pattern() + ")");
        m = oneDependencyPattern.matcher(microIvy);
        if (m.matches()) {
            DefaultModuleDescriptor md = DefaultModuleDescriptor.newBasicInstance(
                ModuleRevisionId.parse(m.group(1)), new Date());
            md.addDependency(new DefaultDependencyDescriptor(ModuleRevisionId.parse(m.group(2)),
                    false));
            return md;
        }

        String p = "(" + mridPattern.pattern() + ")\\s*->\\s*\\{\\s*((?:" + mridPattern.pattern()
                + ",?\\s+)*" + mridPattern.pattern() + ")?\\s*\\}";
        Pattern multipleDependenciesPattern = Pattern.compile(p);
        m = multipleDependenciesPattern.matcher(microIvy);
        if (m.matches()) {
            DefaultModuleDescriptor md = DefaultModuleDescriptor.newBasicInstance(
                ModuleRevisionId.parse(m.group(1)), new Date());
            String mrids = m.group(2);
            if (mrids != null) {
                Collection depMrids = parseMrids(mrids);
                for (Iterator iter = depMrids.iterator(); iter.hasNext();) {
                    ModuleRevisionId dep = (ModuleRevisionId) iter.next();
                    md.addDependency(new DefaultDependencyDescriptor(dep, false));
                }
            }
            return md;
        }
        throw new IllegalArgumentException("invalid micro ivy format: " + microIvy);
    }

    /**
     * Parses a collection of module descriptors in the micro ivy format, separated by double semi
     * columns.
     * 
     * @param microIvy
     *            the text representation of the collection of module descriptors
     * @return the collection of module descriptors parsed
     */
    public static Collection/* <ModuleDescriptor> */parseMicroIvyDescriptors(String microIvy) {
        String[] mds = microIvy.split("\\s*;;\\s*");
        Collection r = new ArrayList();
        for (int i = 0; i < mds.length; i++) {
            r.add(parseMicroIvyDescriptor(mds[i]));
        }
        return r;
    }

    /**
     * Fills a repository with a set of module, using empty files for published artifacts.
     * 
     * @param resolver
     *            the resolver to use to publish the modules
     * @param mds
     *            the descriptors of the modules to put in the repository
     * @throws IOException
     *             if an IO problem occurs while filling the repository
     */
    public static void fillRepository(DependencyResolver resolver,
            Collection/* <ModuleDescriptor> */mds) throws IOException {
        File tmp = File.createTempFile("ivy", "tmp");
        try {
            for (Iterator iter = mds.iterator(); iter.hasNext();) {
                boolean overwrite = false;
                ModuleDescriptor md = (ModuleDescriptor) iter.next();
                resolver.beginPublishTransaction(md.getModuleRevisionId(), overwrite);
                boolean published = false;
                try {
                    XmlModuleDescriptorWriter.write(md, tmp);
                    resolver.publish(md.getMetadataArtifact(), tmp, overwrite);
                    tmp.delete();
                    tmp.createNewFile();
                    Artifact[] artifacts = md.getAllArtifacts();
                    for (int i = 0; i < artifacts.length; i++) {
                        resolver.publish(artifacts[i], tmp, overwrite);
                    }
                    resolver.commitPublishTransaction();
                    published = true;
                } finally {
                    if (!published) {
                        resolver.abortPublishTransaction();
                    }
                }
            }
        } finally {
            tmp.delete();
        }
    }

    /**
     * A file system resolver which can be used with the
     * {@link #fillRepository(DependencyResolver, Collection)} method to create a test case of
     * module descriptor.
     * <p>
     * When finished you should call {@link #cleanTestRepository()}
     * </p>
     */
    public static FileSystemResolver newTestRepository() {
        FileSystemResolver testRepository = new FileSystemResolver();
        testRepository.setName("test");
        String testRepoDir = new File("build/test/test-repo").getAbsolutePath();
        testRepository.addIvyPattern(testRepoDir
                + "/[organisation]/[module]/[revision]/[artifact].[ext]");
        testRepository.addArtifactPattern(testRepoDir
                + "/[organisation]/[module]/[revision]/[artifact].[ext]");
        return testRepository;
    }

    /**
     * Cleans up the test repository.
     * 
     * @see #newTestRepository()
     */
    public static void cleanTestRepository() {
        FileUtil.forceDelete(new File("build/test/test-repo"));
    }

    /**
     * Cleans up the test repository and cache.
     * 
     * @see #newTestSettings()
     */
    public static void cleanTest() {
        cleanTestRepository();
        FileUtil.forceDelete(new File("build/test/cache"));
    }

    /**
     * Init a test resolver as default, useful combined with
     * {@link #fillRepository(DependencyResolver, Collection)}.
     * 
     * @param settings
     *            the settings to initialize
     * @return test settings
     */
    public static IvySettings loadTestSettings(IvySettings settings) {
        settings.setDefaultCache(new File("build/test/cache"));
        settings.addResolver(newTestRepository());
        settings.setDefaultResolver("test");
        return settings;
    }

    /**
     * Create basic resolve data using the given settings
     * 
     * @param settings
     *            the settings to use to create the resolve data
     * @return basic resolve data useful for testing
     */
    public static ResolveData newResolveData(IvySettings settings) {
        return new ResolveData(new ResolveEngine(settings, new EventManager(), new SortEngine(
                settings)), newResolveOptions(settings));
    }

    /**
     * Create basic resolve options using the given settings
     * 
     * @param settings
     *            the settings to use to create the resolve options
     * @return the basic resolve options, useful for testing
     */
    public static ResolveOptions newResolveOptions(IvySettings settings) {
        return new ResolveOptions();
    }
}
