package org.jboss.windup.rules.apps.javaee.rules;


import org.apache.commons.lang3.StringUtils;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.RuleMetadata;
import org.jboss.windup.config.operation.GraphOperation;
import org.jboss.windup.config.phase.PreReportGenerationPhase;
import org.jboss.windup.config.query.Query;
import org.jboss.windup.graph.GraphContext;
import org.jboss.windup.graph.model.LinkModel;
import org.jboss.windup.graph.service.GraphService;
import org.jboss.windup.graph.service.LinkService;
import org.jboss.windup.reporting.model.association.LinkableModel;
import org.jboss.windup.rules.apps.javaee.model.DataSourceModel;
import org.jboss.windup.rules.apps.javaee.model.JNDIResourceModel;
import org.jboss.windup.rules.apps.javaee.model.JmsDestinationModel;
import org.jboss.windup.rules.apps.javaee.model.ThreadPoolModel;
import org.jboss.windup.rules.apps.javaee.service.JNDIResourceService;
import org.ocpsoft.rewrite.config.ConditionBuilder;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;

/**
 * Links server resources (datasources, jms, etc) to EAP 6 resource setup documentation
 */
@RuleMetadata(phase = PreReportGenerationPhase.class, id = "Resolve Links to Server Documentation")
public class ResolveServerResourceLinksRuleProvider extends AbstractRuleProvider
{
    @Override
    public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext) {
        return ConfigurationBuilder.begin()
        .addRule()
        .when(when())
        .perform(new GraphOperation()
        {
            @Override
            public void perform(GraphRewrite event, EvaluationContext context)
            {
                processServerResources(event.getGraphContext());
            }

            @Override
            public String toString()
            {
                return "ResolveServerResourceLinksRule";
            }
        });
    }


    protected ConditionBuilder when()
    {
        return Query.fromType(JNDIResourceModel.class).or(Query.fromType(ThreadPoolModel.class));
    }

    protected void processServerResources(GraphContext context) {
        JNDIResourceService jndiService = new JNDIResourceService(context);
        GraphService<ThreadPoolModel> threadPoolService = new GraphService<>(context, ThreadPoolModel.class);

        for(JNDIResourceModel model : jndiService.findAll()) {
            processJndiResource(context, model);
        }

        for(ThreadPoolModel model : threadPoolService.findAll()) {
            processThreadPool(context, model);
        }
    }

    protected void processJndiResource(GraphContext context, JNDIResourceModel payload)
    {
        if (payload instanceof DataSourceModel)
        {
            processDataSource(context, (DataSourceModel) payload);
        }
        else if (payload instanceof JmsDestinationModel)
        {
            processJMSDestination(context, (JmsDestinationModel) payload);
        }
    }

    private void processJMSDestination(GraphContext context, JmsDestinationModel destination)
    {
        LinkService linkService = new LinkService(context);
        LinkableModel linkable = GraphService.addTypeToModel(context, destination, LinkableModel.class);

        LinkModel jmsDestinationLink = linkService
                    .getOrCreate(
                                "Destination Setup",
                                "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Configuration1.html");
        linkable.addLink(jmsDestinationLink);
    }

    private void processThreadPool(GraphContext context, ThreadPoolModel threadPool) {
        LinkService linkService = new LinkService(context);
        LinkableModel linkable = GraphService.addTypeToModel(context, threadPool, LinkableModel.class);

        LinkModel jmsDestinationLink = linkService
                    .getOrCreate(
                                "Thread Pool Setup",
                                "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Configuring_EJB_Thread_Pools.html");
        linkable.addLink(jmsDestinationLink);
    }

    private void processDataSource(GraphContext context, DataSourceModel dataSource)
    {
        LinkService linkService = new LinkService(context);
        LinkableModel linkable = GraphService.addTypeToModel(context, dataSource, LinkableModel.class);
        if (StringUtils.equals("Oracle", dataSource.getDatabaseTypeName()))
        {
            LinkModel eap6OracleLink = linkService
                        .getOrCreate(
                                    "Oracle DataSource Setup",
                                    "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Example_Datasources.html#Example_Oracle_Datasource");
            linkable.addLink(eap6OracleLink);
        }
        else if (StringUtils.equals("MySQL", dataSource.getDatabaseTypeName()))
        {
            LinkModel lnk = linkService
                        .getOrCreate(
                                    "MySQL DataSource Setup",
                                    "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Example_Datasources.html#Example_MySQL_Datasource1");
            linkable.addLink(lnk);
        }
        else if (StringUtils.equals("Postgres", dataSource.getDatabaseTypeName()))
        {
            LinkModel lnk = linkService
                        .getOrCreate(
                                    "Postgres DataSource Setup",
                                    "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Example_Datasources.html#Example_PostgreSQL_Datasource1");
            linkable.addLink(lnk);
        }
        else if (StringUtils.equals("SqlServer", dataSource.getDatabaseTypeName()))
        {
            LinkModel lnk = linkService
                        .getOrCreate(
                                    "SqlServer DataSource Setup",
                                    "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Example_Datasources.html#Example_Microsoft_SQLServer_Datasource1");
            linkable.addLink(lnk);
        }
        else if (StringUtils.equals("DB2", dataSource.getDatabaseTypeName()))
        {
            LinkModel lnk = linkService
                        .getOrCreate(
                                    "DB2 DataSource Setup",
                                    "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Example_Datasources.html#Example_IBM_DB2_Datasource");
            linkable.addLink(lnk);
        }
        else if (StringUtils.equals("Sybase", dataSource.getDatabaseTypeName()))
        {
            LinkModel lnk = linkService
                        .getOrCreate(
                                    "Sybase DataSource Setup",
                                    "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/sect-Example_Datasources.html#Example_Sybase_Datasource");
            linkable.addLink(lnk);
        }

        LinkModel eap6Link = linkService
                    .getOrCreate(
                                "DataSource Documentation",
                                "https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.4/html/Administration_and_Configuration_Guide/chap-Datasource_Management.html");
        linkable.addLink(eap6Link);
    }

}
