// Copyright (C) 2013 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.google.gerrit.pgm;

import com.google.gerrit.launcher.GerritLauncher;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Properties;

public class JythonShell {
  private static final Logger log = LoggerFactory.getLogger(JythonShell.class);
  private static final String STARTUP_RESOURCE = "com/google/gerrit/pgm/Startup.py";
  private static final String STARTUP_FILE = "Startup.py";

  private Class<?> console;
  private Class<?> pyObject;
  private Class<?> pySystemState;
  private Object shell;
  private ArrayList <String> injectedVariables;

  public JythonShell() {
    Properties env = new Properties();
    // Let us inspect private class members
    env.setProperty("python.security.respectJavaAccessibility", "false");

    File home = GerritLauncher.getHomeDirectory();
    if (home != null) {
      env.setProperty("python.cachedir", new File(home, "jythoncache").getPath());
    }

    // For package introspection and "import com.google" to work,
    // Jython needs to inspect actual .jar files (not just classloader)
    StringBuilder classPath = new StringBuilder();
    final ClassLoader cl = getClass().getClassLoader();
    if (cl instanceof java.net.URLClassLoader) {
      @SuppressWarnings("resource")
      URLClassLoader ucl = (URLClassLoader) cl;
      for (URL u : ucl.getURLs()) {
        if ("file".equals(u.getProtocol())) {
          if (classPath.length() > 0) {
            classPath.append(java.io.File.pathSeparatorChar);
          }
          classPath.append(u.getFile());
        }
      }
    }
    env.setProperty("java.class.path", classPath.toString());

    console = findClass("org.python.util.InteractiveConsole");
    pyObject = findClass("org.python.core.PyObject");
    pySystemState = findClass("org.python.core.PySystemState");

    runMethod(pySystemState, pySystemState, "initialize",
      new Class[]  { Properties.class, Properties.class },
      new Object[] { null, env }
    );

    try {
      shell = console.newInstance();
      log.info("Jython shell instance created.");
    } catch (InstantiationException | IllegalAccessException e) {
      throw noInterpreter(e);
    }
    injectedVariables = new ArrayList<>();
    set("Shell", this);
  }

  protected Object runMethod0(Class<?> klazz, Object instance,
    String name, Class<?>[] sig, Object[] args)
      throws InvocationTargetException {
    try {
      Method m;
      m = klazz.getMethod(name, sig);
      return m.invoke(instance, args);
    } catch (NoSuchMethodException | IllegalAccessException
        | IllegalArgumentException | SecurityException e) {
      throw cannotStart(e);
    }
  }

  protected Object runMethod(Class<?> klazz, Object instance,
    String name, Class<?>[] sig, Object[] args) {
    try {
      return runMethod0(klazz, instance, name, sig, args);
    } catch (InvocationTargetException e) {
      throw cannotStart(e);
    }
  }

  protected Object runInterpreter(String name, Class<?>[] sig, Object[] args) {
    return runMethod(console, shell, name, sig, args);
  }

  protected String getDefaultBanner() {
    return (String)runInterpreter("getDefaultBanner",
                  new Class[] { }, new Object[] { });
  }

  protected void printInjectedVariable(String id) {
    runInterpreter("exec",
      new Class[]  { String.class },
      new Object[] { "print '\"%s\" is \"%s\"' % (\"" + id + "\", " + id + ")" }
    );
  }

  public void run() {
    for (String key : injectedVariables) {
      printInjectedVariable(key);
    }
    reload();
    runInterpreter("interact",
      new Class[]  { String.class, pyObject },
      new Object[] { getDefaultBanner() +
        " running for Gerrit " + com.google.gerrit.common.Version.getVersion(),
        null });
  }

  public void set(String key, Object content) {
    runInterpreter("set",
      new Class[]  { String.class, Object.class },
      new Object[] { key, content }
    );
    injectedVariables.add(key);
  }

  private static Class<?> findClass(String klazzname) {
    try {
      return Class.forName(klazzname);
    } catch (ClassNotFoundException e) {
      throw noShell("Class " + klazzname + " not found", e);
    }
  }

  public void reload() {
    execResource(STARTUP_RESOURCE);
    execFile(GerritLauncher.getHomeDirectory(), STARTUP_FILE);
  }

  protected void execResource(final String p) {
    try (InputStream in = JythonShell.class.getClassLoader().getResourceAsStream(p)) {
      if (in != null) {
        execStream(in, "resource " + p);
      } else {
        log.error("Cannot load resource " + p);
      }
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }

  protected void execFile(final File parent, final String p) {
    try {
      File script = new File(parent, p);
      if (script.canExecute()) {
        runMethod0(console, shell, "execfile",
          new Class[] { String.class },
          new Object[] { script.getAbsolutePath() }
        );
      } else {
        log.info("User initialization file "
          + script.getAbsolutePath()
          + " is not found or not executable");
      }
    } catch (InvocationTargetException e) {
      log.error("Exception occurred while loading file " + p + " : ", e);
    } catch (SecurityException e) {
      log.error("SecurityException occurred while loading file " + p + " : ", e);
    }
  }

  protected void execStream(final InputStream in, final String p) {
    try {
      runMethod0(console, shell, "execfile",
        new Class[] { InputStream.class, String.class },
        new Object[] { in, p }
      );
    } catch (InvocationTargetException e) {
      log.error("Exception occurred while loading " + p + " : ", e);
    }
  }

  private static UnsupportedOperationException noShell(final String m, Throwable why) {
    final String prefix = "Cannot create Jython shell: ";
    final String postfix = "\n     (You might need to install jython.jar in the lib directory)";
    return new UnsupportedOperationException(prefix + m + postfix, why);
  }

  private static UnsupportedOperationException noInterpreter(Throwable why) {
    final String msg = "Cannot create Python interpreter";
    return noShell(msg, why);
  }

  private static UnsupportedOperationException cannotStart(Throwable why) {
    final String msg = "Cannot start Jython shell";
    return new UnsupportedOperationException(msg, why);
  }
}
