/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed 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.gradle.api.internal.artifacts.resolution;

import com.google.common.collect.*;

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.id.ModuleRevisionId;

import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.artifacts.resolution.*;
import org.gradle.api.internal.artifacts.ModuleMetadataProcessor;
import org.gradle.api.internal.artifacts.configurations.ConfigurationContainerInternal;
import org.gradle.api.internal.artifacts.configurations.ConfigurationInternal;
import org.gradle.api.internal.artifacts.ivyservice.*;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingArtifactResolver;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ResolveIvyFactory;
import org.gradle.api.internal.artifacts.metadata.DefaultDependencyMetaData;
import org.gradle.api.internal.artifacts.metadata.DefaultModuleVersionArtifactMetaData;
import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository;
import org.gradle.internal.Factory;
import org.gradle.internal.Transformers;
import org.gradle.util.CollectionUtils;

import java.util.*;

public class DefaultArtifactResolutionQuery implements ArtifactResolutionQuery {
    private final ConfigurationContainerInternal configurationContainer;
    private final RepositoryHandler repositoryHandler;
    private final ResolveIvyFactory ivyFactory;
    private final ModuleMetadataProcessor metadataProcessor;
    private final CacheLockingManager lockingManager;

    private Set<ModuleComponentIdentifier> componentIds = Sets.newHashSet();
    private Class<? extends SoftwareComponent<?>> componentType;
    private Set<Class<? extends SoftwareArtifact>> artifactTypes = Sets.newHashSet();

    public DefaultArtifactResolutionQuery(ConfigurationContainerInternal configurationContainer, RepositoryHandler repositoryHandler,
                                          ResolveIvyFactory ivyFactory, ModuleMetadataProcessor metadataProcessor, CacheLockingManager lockingManager) {
        this.configurationContainer = configurationContainer;
        this.repositoryHandler = repositoryHandler;
        this.ivyFactory = ivyFactory;
        this.metadataProcessor = metadataProcessor;
        this.lockingManager = lockingManager;
    }

    public ArtifactResolutionQuery forComponents(Set<ModuleComponentIdentifier> componentIds) {
        this.componentIds.addAll(componentIds);
        return this;
    }

    @SuppressWarnings("unchecked")
    public <T extends SoftwareArtifact, U extends SoftwareComponent<T>> ArtifactResolutionQuery withArtifacts(Class<U> componentType, Class<T>... artifactTypes) {
        this.componentType = componentType;
        if (artifactTypes.length == 0) {
            this.artifactTypes = (Set) Sets.newHashSet(JvmLibrarySourcesArtifact.class, JvmLibraryJavadocArtifact.class);
        } else {
            this.artifactTypes.addAll(Arrays.asList(artifactTypes));
        }
        return this;
    }

    public ArtifactResolutionQueryResult execute() {
        List<ResolutionAwareRepository> repositories = CollectionUtils.collect(repositoryHandler, Transformers.cast(ResolutionAwareRepository.class));
        ConfigurationInternal configuration = configurationContainer.detachedConfiguration();
        final DependencyToModuleVersionResolver resolver = ivyFactory.create(configuration, repositories, metadataProcessor);

        return lockingManager.useCache("resolve artifacts", new Factory<ArtifactResolutionQueryResult>() {
            public ArtifactResolutionQueryResult create() {
                Set<JvmLibrary> jvmLibraries = Sets.newHashSet();
                Set<UnresolvedSoftwareComponent> unresolvedComponents = Sets.newHashSet();

                for (ModuleComponentIdentifier componentId : componentIds) {
                    BuildableModuleVersionResolveResult moduleResolveResult = new DefaultBuildableModuleVersionResolveResult();
                    resolver.resolve(new DefaultDependencyMetaData(new DefaultDependencyDescriptor(toModuleRevisionId(componentId), true)), moduleResolveResult);

                    if (moduleResolveResult.getFailure() != null) {
                        unresolvedComponents.add(new DefaultUnresolvedSoftwareComponent(componentId, moduleResolveResult.getFailure()));
                    } else {
                        moduleResolveResult.setArtifactResolver(new ErrorHandlingArtifactResolver(moduleResolveResult.getArtifactResolver()));
                        List<JvmLibraryArtifact> jvmLibraryArtifacts = Lists.newArrayList();
                        for (Class<? extends SoftwareArtifact> artifactType : artifactTypes) {
                            if (artifactType == JvmLibraryJavadocArtifact.class) {
                                Artifact artifact = new DefaultArtifact(toModuleRevisionId(componentId), null, componentId.getModule(), "javadoc", "jar", ImmutableMap.of("m:classifier", "javadoc"));
                                DefaultBuildableArtifactResolveResult artifactResolveResult = new DefaultBuildableArtifactResolveResult();
                                moduleResolveResult.getArtifactResolver().resolve(new DefaultModuleVersionArtifactMetaData(moduleResolveResult.getId(), artifact), artifactResolveResult);
                                if (artifactResolveResult.getFailure() != null) {
                                    // TODO
                                } else {
                                    jvmLibraryArtifacts.add(new DefaultJvmLibraryJavadocArtifact(artifactResolveResult.getFile()));
                                }
                            } else if (artifactType == JvmLibrarySourcesArtifact.class) {
                                Artifact artifact = new DefaultArtifact(toModuleRevisionId(componentId), null, componentId.getModule(), "source", "jar", ImmutableMap.of("m:classifier", "sources"));
                                DefaultBuildableArtifactResolveResult artifactResolveResult = new DefaultBuildableArtifactResolveResult();
                                moduleResolveResult.getArtifactResolver().resolve(new DefaultModuleVersionArtifactMetaData(moduleResolveResult.getId(), artifact), artifactResolveResult);
                                if (artifactResolveResult.getFailure() != null) {
                                    // TODO
                                } else {
                                    jvmLibraryArtifacts.add(new DefaultJvmLibrarySourcesArtifact(artifactResolveResult.getFile()));
                                }
                            }
                        }

                        jvmLibraries.add(new DefaultJvmLibrary(componentId, jvmLibraryArtifacts));
                    }
                }

                return new DefaultArtifactResolutionQueryResult(jvmLibraries, unresolvedComponents);
            }
        });
    }

    private ModuleRevisionId toModuleRevisionId(ModuleComponentIdentifier componentId) {
        return ModuleRevisionId.newInstance(componentId.getGroup(), componentId.getModule(), componentId.getVersion());
    }
}

@@ -6214,32 +6214,43 @@
                 
+ int x = 1;
  // TODO%0A       
@@ -7180,16 +7180,27 @@
         
+ int x = 1;
  // TODO

make checkstyle happy