
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

import java.time.Instant;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.nio.file.StandardOpenOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.time.*;// Timestamp in cut-filename
import java.io.ByteArrayOutputStream; // for SODA direct streaming doSubimgStream

import vo.parameter.*;

class SodaImpl implements Soda
{
   private static final Logger LOGGER = Logger.getLogger(SodaImpl.class.getName());
   private static Settings.FITSPaths fitsPaths = null;

   private SodaImpl() {}


   public SodaImpl(Settings.FITSPaths fitsPaths)
   {
      LOGGER.fine("trace");
      this.fitsPaths = fitsPaths;
   }


   public int doStream(String relPathname, int hdunum,
         Pos pos, Band band, Time time, Pol pol, Pixeli[] pixeli,
         OutputStream outputStream)  throws IOException, InterruptedException
   {
      Instant start = Instant.now();
      LOGGER.fine("trace");

		if(outputStream == null)
			LOGGER.finest("supplied outputStream for cut-file is null");
			// FIXME throw excpetion here

      /*/ DBG start
		Pixeli[] pixeli =
      {
      new Pixeli(0,0,' '),
      new Pixeli(0,0,' '),
      new Pixeli(10,20,'x')
      };
     // DBG end*/

		boolean has_overlap  = false;
		String boundsString = "";
		JsonEncoder jReq = new JsonEncoder();
		jReq.add(pos);
		jReq.add(band);
		jReq.add(time);
		jReq.add(pol);
		jReq.add(pixeli);
		String coordString = jReq.toString();
		LOGGER.finest("coordString: " + coordString);

		String[] cmd = new String[5];
		cmd[0] = "/usr/local/bin/vlkb";
		cmd[1] = "cutout";
		cmd[2] = fitsPaths.surveys() + "/" + relPathname;
		cmd[3] = String.valueOf(hdunum);
		cmd[4] = coordString;
		LOGGER.finest(String.join(" ", cmd));

		StringBuilder errorStrBuilder = new StringBuilder();

		ExecCmd exec = new ExecCmd();
		exec.doRun(outputStream, cmd, errorStrBuilder);
		int rc = exec.exitValue;
		LOGGER.finest("exec cutout exitValue: " + rc);
		LOGGER.finer("EXECTIME    cutoutDone: " + Duration.between(start, Instant.now()));

		if(rc == 0)
		{
			return rc; // OK
		}
		else if(rc == 1)
		{
			return rc; // OK, but no overlap
		}
		else
		{
			throw new IllegalArgumentException(
					"overlap computation could not be completed with the given arguments. "
					+ errorStrBuilder.toString());
		}
	}




	public int doStream(String relPathname, int hdunum,
			String pixels, OutputStream outputStream)  throws IOException, InterruptedException
	{
		Instant start = Instant.now();
		LOGGER.fine("trace");

		if(outputStream == null)
			LOGGER.finest("supplied outputStream for cut-file is null");

		final boolean isDavCall= relPathname.startsWith("http://") || relPathname.startsWith("https://");
		final boolean isAbsPath= relPathname.startsWith("/");
		String absPathname = (isDavCall || isAbsPath) ? relPathname
			: (fitsPaths.surveys() +"/"+ relPathname);

		String[] cmd = new String[5];
		cmd[0] = "/usr/local/bin/vlkb";
		cmd[1] = (isDavCall) ? "imcopydav" : "imcopy";
		cmd[2] = absPathname;
		cmd[3] = String.valueOf(hdunum);
		cmd[4] = pixels;
		LOGGER.finest(String.join(" ", cmd));

		StringBuilder errorStrBuilder = new StringBuilder();

		ExecCmd exec = new ExecCmd();
		exec.doRun(outputStream, cmd, errorStrBuilder);
		int rc = exec.exitValue;
		LOGGER.finest("exec cutout exitValue: " + rc);
		LOGGER.finer("EXECTIME    cutoutDone: " + Duration.between(start, Instant.now()));

		if(rc == 0)
		{
			return rc; // OK
		}
		else if(rc == 1)
		{
			return rc; // OK, but no overlap
		}
		else
		{
			throw new IllegalArgumentException(
					"overlap computation could not be completed with the given arguments. "
					+ errorStrBuilder.toString());
		}
	}


	public int doStreamHeader(String relPathname, int hdunum,
			OutputStream outputStream)  throws IOException, InterruptedException
	{
		Instant start = Instant.now();
		LOGGER.fine("trace");

		if(outputStream == null)
			LOGGER.finest("supplied response outputStream is null");

		final boolean isAbsPath= relPathname.startsWith("/");
		String absPathname = isAbsPath ? relPathname : (fitsPaths.surveys() +"/"+ relPathname);

		String[] cmd = new String[4];
		cmd[0] = "/usr/local/bin/vlkb";
		cmd[1] = "header";
		cmd[2] = "--extnum=" + String.valueOf(hdunum-1);
		cmd[3] = absPathname;
		LOGGER.finest(String.join(" ", cmd));

		StringBuilder errorStrBuilder = new StringBuilder();

		ExecCmd exec = new ExecCmd();
		exec.doRun(outputStream, cmd, errorStrBuilder);
		int rc = exec.exitValue;
		LOGGER.finest("exec header exitValue: " + rc);
		LOGGER.finer("EXECTIME    headerDone: " + Duration.between(start, Instant.now()));

		if(rc == 0)
		{
			return rc; // OK
		}
		else
		{
			throw new IllegalArgumentException("header could not be retrieved (rc="
					+ rc + ") " + errorStrBuilder.toString());
		}
	}


}

