/*
 * Copyright (C) 2015 Google Inc.
 *
 * 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.googlecode.android_scripting;

import com.googlecode.android_scripting.interpreter.InterpreterConstants;
import com.trilead.ssh2.StreamGobbler;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;

public class Process {

  private static final int DEFAULT_BUFFER_SIZE = 8192;

  private final List<String> mArguments;
  private final Map<String, String> mEnvironment;

  private static final int PID_INIT_VALUE = -1;

  private File mBinary;
  private String mName;
  private long mStartTime;
  private long mEndTime;

  protected final AtomicInteger mPid;
  protected FileDescriptor mFd;
  protected OutputStream mOut;
  protected InputStream mIn;
  protected File mLog;

  public Process() {
    mArguments = new ArrayList<String>();
    mEnvironment = new HashMap<String, String>();
    mPid = new AtomicInteger(PID_INIT_VALUE);
  }

  public void addArgument(String argument) {
    mArguments.add(argument);
  }

  public void addAllArguments(List<String> arguments) {
    mArguments.addAll(arguments);
  }

  public void putAllEnvironmentVariables(Map<String, String> environment) {
    mEnvironment.putAll(environment);
  }

  public void putEnvironmentVariable(String key, String value) {
    mEnvironment.put(key, value);
  }

  public void setBinary(File binary) {
    if (!binary.exists()) {
      throw new RuntimeException("Binary " + binary + " does not exist!");
    }
    mBinary = binary;
  }

  public Integer getPid() {
    return mPid.get();
  }

  public FileDescriptor getFd() {
    return mFd;
  }

  public OutputStream getOut() {
    return mOut;
  }

  public OutputStream getErr() {
    return getOut();
  }

  public File getLogFile() {
    return mLog;
  }

  public InputStream getIn() {
    return mIn;
  }

  public void start(final Runnable shutdownHook) {
    if (isAlive()) {
      throw new RuntimeException("Attempted to start process that is already running.");
    }

    String binaryPath = mBinary.getAbsolutePath();
    Log.v("Executing " + binaryPath + " with arguments " + mArguments + " and with environment "
        + mEnvironment.toString());

    int[] pid = new int[1];
    String[] argumentsArray = mArguments.toArray(new String[mArguments.size()]);
    mLog = new File(String.format("%s/%s.log", InterpreterConstants.SDCARD_SL4A_ROOT, getName()));

    mFd =
        Exec.createSubprocess(binaryPath, argumentsArray, getEnvironmentArray(),
            getWorkingDirectory(), pid);
    mPid.set(pid[0]);
    mOut = new FileOutputStream(mFd);
    mIn = new StreamGobbler(new FileInputStream(mFd), mLog, DEFAULT_BUFFER_SIZE);
    mStartTime = System.currentTimeMillis();

    new Thread(new Runnable() {
      public void run() {
        int result = Exec.waitFor(mPid.get());
        mEndTime = System.currentTimeMillis();
        int pid = mPid.getAndSet(PID_INIT_VALUE);
        Log.v("Process " + pid + " exited with result code " + result + ".");
        try {
          mIn.close();
        } catch (IOException e) {
          Log.e(e);
        }
        try {
          mOut.close();
        } catch (IOException e) {
          Log.e(e);
        }
        if (shutdownHook != null) {
          shutdownHook.run();
        }
      }
    }).start();
  }

  private String[] getEnvironmentArray() {
    List<String> environmentVariables = new ArrayList<String>();
    for (Entry<String, String> entry : mEnvironment.entrySet()) {
      environmentVariables.add(entry.getKey() + "=" + entry.getValue());
    }
    String[] environment = environmentVariables.toArray(new String[environmentVariables.size()]);
    return environment;
  }

  public void kill() {
    if (isAlive()) {
      android.os.Process.killProcess(mPid.get());
      Log.v("Killed process " + mPid);
    }
  }

  public boolean isAlive() {
    return (mFd != null && mFd.valid()) && mPid.get() != PID_INIT_VALUE;
  }

  public String getUptime() {
    long ms;
    if (!isAlive()) {
      ms = mEndTime - mStartTime;
    } else {
      ms = System.currentTimeMillis() - mStartTime;
    }
    StringBuilder buffer = new StringBuilder();
    int days = (int) (ms / (1000 * 60 * 60 * 24));
    int hours = (int) (ms % (1000 * 60 * 60 * 24)) / 3600000;
    int minutes = (int) (ms % 3600000) / 60000;
    int seconds = (int) (ms % 60000) / 1000;
    if (days != 0) {
      buffer.append(String.format("%02d:%02d:", days, hours));
    } else if (hours != 0) {
      buffer.append(String.format("%02d:", hours));
    }
    buffer.append(String.format("%02d:%02d", minutes, seconds));
    return buffer.toString();
  }

  public String getName() {
    return mName;
  }

  public void setName(String name) {
    mName = name;
  }

  public String getWorkingDirectory() {
    return null;
  }
}
