/*
 * Copyright 2017 NAVER Corp.
 *
 * 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.navercorp.pinpoint.profiler.plugin;

import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.instrument.DynamicTransformTrigger;
import com.navercorp.pinpoint.profiler.instrument.InstrumentEngine;
import com.navercorp.pinpoint.bootstrap.plugin.ApplicationTypeDetector;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.JdbcUrlParserV2;

import java.lang.instrument.ClassFileTransformer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Woonduk Kang(emeroad)
 */
public class DefaultPluginContextLoadResult implements PluginContextLoadResult {

    private final URL[] pluginJars;
    private final InstrumentEngine instrumentEngine;

    private final ProfilerConfig profilerConfig;
    private final DynamicTransformTrigger dynamicTransformTrigger;

    private List<SetupResult> lazy;

    public DefaultPluginContextLoadResult(ProfilerConfig profilerConfig, DynamicTransformTrigger dynamicTransformTrigger, InstrumentEngine instrumentEngine,
                                          URL[] pluginJars) {
        if (profilerConfig == null) {
            throw new NullPointerException("profilerConfig must not be null");
        }
        if (dynamicTransformTrigger == null) {
            throw new NullPointerException("dynamicTransformTrigger must not be null");
        }
        if (instrumentEngine == null) {
            throw new NullPointerException("instrumentEngine must not be null");
        }
        if (pluginJars == null) {
            throw new NullPointerException("pluginJars must not be null");
        }
        this.profilerConfig = profilerConfig;
        this.dynamicTransformTrigger = dynamicTransformTrigger;

        this.pluginJars = pluginJars;
        this.instrumentEngine = instrumentEngine;
    }


    private List<SetupResult> getProfilerPluginContextList() {
        if (lazy == null) {
            lazy = load();
        }
        return lazy;
    }


    private List<SetupResult> load() {
        PluginSetup pluginSetup = new DefaultPluginSetup(profilerConfig, instrumentEngine, dynamicTransformTrigger);
        final ProfilerPluginLoader loader = new ProfilerPluginLoader(profilerConfig, pluginSetup, instrumentEngine);
        List<SetupResult> load = loader.load(pluginJars);
        return load;
    }

    @Override
    public List<ClassFileTransformer> getClassFileTransformer() {
        // TODO Need plugin context level grouping
        List<SetupResult> profilerPluginContextList = getProfilerPluginContextList();
        List<ClassFileTransformer> transformerList = new ArrayList<ClassFileTransformer>();
        for (SetupResult pluginContext : profilerPluginContextList) {
            List<ClassFileTransformer> classTransformerList = pluginContext.getClassTransformerList();
            transformerList.addAll(classTransformerList);
        }
        return transformerList;
    }



    @Override
    public List<ApplicationTypeDetector> getApplicationTypeDetectorList() {

        List<ApplicationTypeDetector> registeredDetectors = new ArrayList<ApplicationTypeDetector>();

        List<SetupResult> profilerPluginContextList = getProfilerPluginContextList();
        for (SetupResult context : profilerPluginContextList) {
            List<ApplicationTypeDetector> applicationTypeDetectors = context.getApplicationTypeDetectors();
            registeredDetectors.addAll(applicationTypeDetectors);
        }

        return registeredDetectors;
    }

    @Override
    public List<JdbcUrlParserV2> getJdbcUrlParserList() {
        List<JdbcUrlParserV2> result = new ArrayList<JdbcUrlParserV2>();

        List<SetupResult> profilerPluginContextList = getProfilerPluginContextList();
        for (SetupResult context : profilerPluginContextList) {
            List<JdbcUrlParserV2> jdbcUrlParserList = context.getJdbcUrlParserList();
            result.addAll(jdbcUrlParserList);
        }

        return result;
    }

}

@@ -981,16 +981,73 @@
 arserV2;
+%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0A%0Aimport
@@ -1282,24 +1282,101 @@
 adResult %7B%0A%0A
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());%0A%0A
     private 
@@ -1574,32 +1574,38 @@
 r;%0A%0A    private 
+final 
 List%3CSetupResult
@@ -1606,20 +1606,31 @@
 Result%3E 
-lazy
+setupResultList
 ;%0A%0A    p
@@ -2572,166 +2572,50 @@
     
-%7D%0A%0A%0A    private List%3CSetupResult%3E getProfilerPluginContextList() %7B%0A        if (lazy == null) %7B%0A            lazy = load();%0A        %7D%0A        return lazy;%0A    %7D
+    this.setupResultList = load();%0A    %7D%0A%0A
 %0A%0A%0A 
@@ -2648,24 +2648,60 @@
 t%3E load() %7B%0A
+        logger.info(%22load plugin%22);%0A
         Plug
@@ -3151,93 +3151,13 @@
     
-List%3CSetupResult%3E profilerPluginContextList = getProfilerPluginContextList();%0A       
+final
  Lis
@@ -3278,36 +3278,26 @@
 ntext : 
-profilerPluginContex
+setupResul
 tList) %7B
@@ -3600,32 +3600,38 @@
 st() %7B%0A%0A        
+final 
 List%3CApplication
@@ -3713,94 +3713,8 @@
 );%0A%0A
-        List%3CSetupResult%3E profilerPluginContextList = getProfilerPluginContextList();%0A
     
@@ -3744,36 +3744,26 @@
 ntext : 
-profilerPluginContex
+setupResul
 tList) %7B
@@ -4063,32 +4063,38 @@
 ist() %7B%0A        
+final 
 List%3CJdbcUrlPars
@@ -4147,94 +4147,8 @@
 );%0A%0A
-        List%3CSetupResult%3E profilerPluginContextList = getProfilerPluginContextList();%0A
     
@@ -4182,28 +4182,18 @@
 t : 
-profilerPluginContex
+setupResul
 tLis

remove lazyloading