// Copyright (C) 2014 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.scripting.groovyprovider;

import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import com.google.gerrit.server.plugins.AbstractPreloadedPluginScanner;
import com.google.gerrit.server.plugins.InvalidPluginException;
import com.google.gerrit.server.plugins.Plugin.ApiType;

import groovy.lang.Binding;
import groovy.lang.Script;
import groovy.util.ResourceException;
import groovy.util.ScriptException;

import org.codehaus.groovy.runtime.InvokerHelper;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;

public class GroovyPluginScanner extends AbstractPreloadedPluginScanner {

  public GroovyPluginScanner(String pluginName, GroovyPluginScriptEngine scriptEngine, File srcFile)
      throws InvalidPluginException {
    super(pluginName, getPluginVersion(srcFile), load(scriptEngine, srcFile), ApiType.PLUGIN);
  }

  private static String getPluginVersion(File srcFile) {
    String srcFileName = srcFile.getName();
    int dashPos = srcFileName.lastIndexOf('-');
    int dotPos = srcFileName.lastIndexOf('.');
    return dashPos > 0 ? srcFileName.substring(dashPos + 1, dotPos) : "0";
  }

  @Override
  public <T> Optional<T> getResource(String resourcePath, Class<? extends T> resourceClass) {
    return Optional.absent();
  }

  @Override
  public Optional<InputStream> getResourceInputStream(String resourcePath)
      throws IOException {
    return Optional.absent();
  }

  @Override
  public <T> Enumeration<T> resources(Class<? extends T> resourceClass) {
    return Collections.emptyEnumeration();
  }

  public static Set<Class<?>> load(GroovyPluginScriptEngine scriptEngine, File srcFile) throws InvalidPluginException {
    try {
      return scanGroovyScriptBindings(scriptEngine.loadScriptByName(srcFile
          .getName()));
    } catch (ResourceException | ScriptException e) {
      throw new InvalidPluginException(
          "Cannot compile and execute Groovy script " + srcFile, e);
    }
  }

  private static Set<Class<?>> scanGroovyScriptBindings(Class<?> scriptClass)
      throws InvalidPluginException {
    Set<Class<?>> classes = Sets.newHashSet();

    try {
      Method mainMethod = scriptClass.getMethod("main", String[].class);
      int modifiers = mainMethod.getModifiers();
      if (mainMethod != null && Modifier.isPublic(modifiers)
          && Modifier.isStatic(modifiers)) {
        classes.addAll(getMainBindings(scriptClass));
      }
    } catch (NoSuchMethodException e) {
      classes.add(scriptClass);

    } catch (SecurityException e) {
      throw new InvalidPluginException("Cannot access Groovy script class "
          + scriptClass.getName(), e);
    }
    return classes;
  }

  private static Set<Class<?>> getMainBindings(Class<?> scriptClass)
      throws InvalidPluginException {
    Set<Class<?>> classes = Sets.newHashSet();
    Binding binding = new Binding();
    Script script = InvokerHelper.createScript(scriptClass, binding);
    script.run();

    for (Object variable : binding.getVariables().keySet()) {
      Object value = binding.getVariable(variable.toString());
      if (value == null) {
        continue;
      }

      if (ArrayList.class.isAssignableFrom(value.getClass())) {
        classes.addAll(scanArrayOfObjectOrClass(value));
      } else {
        classes.add(scanObjectOrClass(value));
      }
    }

    return classes;
  }

  private static Set<Class<?>> scanArrayOfObjectOrClass(Object value)
      throws InvalidPluginException {
    Set<Class<?>> classes = Sets.newHashSet();
    ArrayList<?> list = (ArrayList<?>) value;
    for (Object element : list) {
      if (element == null) {
        continue;
      }
      classes.add(scanObjectOrClass(element));
    }
    return classes;
  }

  private static Class<?> scanObjectOrClass(Object element)
      throws InvalidPluginException {
    if (Class.class.isAssignableFrom(element.getClass())) {
      return (Class<?>) element;
    } else {
      return element.getClass();
    }
  }
}
