/*
 * Copyright 2015 Michael Rozumyanskiy
 *
 * 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 io.michaelrocks.lightsaber.processor.descriptors;

import io.michaelrocks.lightsaber.internal.InstanceProvider;
import org.objectweb.asm.Type;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ModuleDescriptor {
    private final Type moduleType;
    private final List<ProviderDescriptor> providers;

    public ModuleDescriptor(final Type moduleType, final List<ProviderDescriptor> providers) {
        this.moduleType = moduleType;
        this.providers = Collections.unmodifiableList(providers);
    }

    public Type getModuleType() {
        return moduleType;
    }

    public List<ProviderDescriptor> getProviders() {
        return providers;
    }

    public static class Builder {
        private final Type moduleType;
        private final List<ProviderDescriptor> providers = new ArrayList<>();

        public Builder(final Type moduleType) {
            this.moduleType = moduleType;
        }

        public Type getModuleType() {
            return moduleType;
        }

        public Builder addProviderField(final QualifiedFieldDescriptor providerField) {
            final Type providerType =
                    Type.getObjectType(moduleType.getInternalName() + "$$Provider$$" + providers.size());
            final QualifiedType providableType =
                    new QualifiedType(providerField.getRawType(), providerField.getQualifier());
            final ProviderDescriptor provider =
                    new ProviderDescriptor(providerType, providableType, providerField, moduleType);
            return addProvider(provider);
        }

        public Builder addProviderMethod(final QualifiedMethodDescriptor providerMethod, final ScopeDescriptor scope) {
            final Type providerType =
                    Type.getObjectType(moduleType.getInternalName() + "$$Provider$$" + providers.size());
            final QualifiedType providableType =
                    new QualifiedType(providerMethod.getReturnType().getRawType(), providerMethod.getResultQualifier());
            final Type delegatorType = scope != null ? scope.getProviderType() : null;
            final ProviderDescriptor provider =
                    new ProviderDescriptor(providerType, providableType, providerMethod, moduleType, delegatorType);
            return addProvider(provider);
        }

        public Builder addProvider(final ProviderDescriptor provider) {
            providers.add(provider);
            return this;
        }

        public ModuleDescriptor build() {
            return new ModuleDescriptor(moduleType, providers);
        }
    }
}

@@ -661,69 +661,8 @@
 s;%0A%0A
-import io.michaelrocks.lightsaber.internal.InstanceProvider;%0A
 impo
@@ -834,24 +834,65 @@
 moduleType;%0A
+    private final Type configuratorType;%0A
     private 
@@ -984,16 +984,57 @@
 uleType,
+ final Type configuratorType,%0A           
  final L
@@ -1100,32 +1100,82 @@
 e = moduleType;%0A
+        this.configuratorType = configuratorType;%0A
         this.pro
@@ -1291,32 +1291,112 @@
 uleType;%0A    %7D%0A%0A
+    public Type getConfiguratorType() %7B%0A        return configuratorType;%0A    %7D%0A%0A
     public List%3C
@@ -1530,32 +1530,77 @@
 ype moduleType;%0A
+        private final Type configuratorType;%0A
         private 
@@ -1744,32 +1744,282 @@
 e = moduleType;%0A
+            final String moduleNameWithDollars = moduleType.getInternalName().replace('/', '$');%0A            this.configuratorType = Type.getObjectType(%0A                    %22io/michaelrocks/lightsaber/InjectorConfigurator$%22 + moduleNameWithDollars);%0A
         %7D%0A%0A     
@@ -3646,24 +3646,42 @@
 (moduleType,
+ configuratorType,
  providers);

Add a configurator type to the module descriptor