package com.katasoft.cinder.granite.as3;

import com.katasoft.cinder.granite.as3.reflect.AbstractRemoteDestination;
import org.granite.generator.as3.As3Type;
import org.granite.generator.as3.JavaAs3GroovyTransformer;
import org.granite.generator.as3.JavaAs3Input;
import org.granite.generator.as3.reflect.JavaInterface;
import org.granite.generator.as3.reflect.JavaRemoteDestination;
import org.granite.generator.as3.reflect.JavaType;
import org.granite.generator.gsp.GroovyTemplate;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Bryan Turner
 * @since 0.1
 */
public class CinderAs3GroovyTransformer extends JavaAs3GroovyTransformer {

    public List<JavaInterface> getJavaTypeInterfaces(Class<?> clazz) {
        List<JavaInterface> interfazes = new ArrayList<JavaInterface>();
        for (Class<?> interfaze : clazz.getInterfaces()) {
            if (getConfig().isGenerated(interfaze)) {
                JavaType javaType = getJavaType(interfaze);
                if (javaType instanceof JavaRemoteDestination) {
                    javaType = ((JavaRemoteDestination) javaType).convertToJavaInterface();
                } else if (javaType instanceof AbstractRemoteDestination) {
                    javaType = ((AbstractRemoteDestination) javaType).convertToJavaInterface();
                }
                interfazes.add((JavaInterface) javaType);
            }
        }
        return interfazes;
    }

    @Override
    protected File getOutputFile(JavaAs3Input input, GroovyTemplate template, File outputDir) {
        //For remote destinations, we want to use custom output names. The default would be Name and NameBase. What we
        //want to use is AmfName and Name (where the "base" object has the straight name and the "derived" object has
        //the Amf prefix. This is because the generated base version emits an interface, and we want the "derived" type
        //to implement it. That way we get SomeService (interface [base]) which is implemented by AmfSomeService (class
        //[derived]).
        //We could generate this the other way around, where we leave the "derived" name alone and put "Amf" in the
        //base class's name, but that has the wrong semantics for what gets regenerated. We want the interface to
        //always be regenerated (in case it changes), and allow the implementing class to be modified and maintained if
        //necessary. By forcing the interface to be regenerated every time, we ensure the implementation class always
        //has the right methods for the service.
        JavaType.Kind kind = getKind(input.getType());
        if (kind == JavaType.Kind.REMOTE_DESTINATION) {
            As3Type as3Type = input.getJavaType().getAs3Type();

            StringBuilder sb = new StringBuilder()
                    .append(outputDir.getAbsolutePath())
                    .append(File.separatorChar)
                    .append(as3Type.getPackageName().replace('.', File.separatorChar))
                    .append(File.separatorChar);
            if (!template.isBase()) {
                sb.append("Amf");
            }
            sb.append(as3Type.getName()).append(".as");

            return new File(sb.toString());
        }
        return super.getOutputFile(input, template, outputDir);
    }
}
