/*
 * 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 com.michaelrocks.lightsaber.processor;

import com.michaelrocks.lightsaber.processor.analysis.AnalysisClassFileVisitor;
import com.michaelrocks.lightsaber.processor.injection.InjectionClassFileVisitor;
import com.michaelrocks.lightsaber.processor.io.ClassFileReader;
import com.michaelrocks.lightsaber.processor.io.ClassFileWriter;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class LightsaberClassProcessor {
    private final ClassFileReader classFileReader;
    private final ClassFileWriter classFileWriter;

    private final ProcessorContext processorContext = new ProcessorContext();

    public LightsaberClassProcessor(final ClassFileReader classFileReader, final ClassFileWriter classFileWriter) {
        this.classFileWriter = classFileWriter;
        this.classFileReader = classFileReader;
    }

    public void processClasses() throws IOException {
        performAnalysis();
        processorContext.dump();
        checkDependenciesAreResolved();
        generateProviders();
        generateGlobalModule();
        patchInjectorCreation();
        patchInjection();
    }

    private void performAnalysis() throws IOException {
        final AnalysisClassFileVisitor analysisVisitor = new AnalysisClassFileVisitor(processorContext);
        classFileReader.accept(analysisVisitor);
        checkErrors();
    }

    private void checkDependenciesAreResolved() {
        // TODO: Implement.
    }

    private void generateProviders() {
        // TODO: Implement.
    }

    private void generateGlobalModule() {
        // TODO: Implement.
    }

    private void patchInjectorCreation() {
        // TODO: Implement.
    }

    private void patchInjection() throws IOException {
        // TODO: Implement.

        final InjectionClassFileVisitor injectionVisitor = new InjectionClassFileVisitor(classFileWriter);
        classFileReader.accept(injectionVisitor);
    }

    private void checkErrors() throws ProcessingException {
        if (processorContext.hasErrors()) {
            throw new ProcessingException(composeErrorMessage());
        }
    }

    private String composeErrorMessage() {
        final StringBuilder builder = new StringBuilder();
        for (final Map.Entry<String, List<Exception>> entry : processorContext.getErrors().entrySet()) {
            final String path = entry.getKey();
            for (final Exception error : entry.getValue()) {
                builder
                        .append(System.lineSeparator())
                        .append(path)
                        .append(": ")
                        .append(error.getMessage());
            }
        }
        return builder.toString();
    }
}

@@ -942,31 +942,91 @@
 er;%0A
-%0Aimport java.io.IOExcep
+import org.objectweb.asm.Type;%0A%0Aimport java.io.IOException;%0Aimport java.util.Collec
 tion
@@ -2087,37 +2087,468 @@
 d() 
-%7B%0A        // TODO: Implement.
+throws ProcessingException %7B%0A        final DependencyGraph dependencyGraph = new DependencyGraph(processorContext);%0A        final Collection%3CType%3E unresolvedDependencies = dependencyGraph.getUnresolvedDependencies();%0A        for (final Type unresolvedDependency : unresolvedDependencies) %7B%0A            processorContext.reportError(%0A                    new ProcessingException(%22Unresolved dependency: %22 + unresolvedDependency));%0A        %7D%0A        checkErrors();
 %0A   

Check that all dependencies are resolved in LightsaberClassProcessor