content: /*
  The contents of this file are subject to the Mozilla Public License
  Version 1.1 (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.mozilla.org/MPL/
  
  Software distributed under the License is distributed on an "AS IS"
  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  License for the specific language governing rights and limitations
  under the License.
  
  The Original Code is collection of files collectively known as Open Camera.
  
  The Initial Developer of the Original Code is Almalence Inc.
  Portions created by Initial Developer are Copyright (C) 2013 
  by Almalence Inc. All Rights Reserved.
   */
  
  package com.almalence.plugins.processing.sequence;
  
  import java.io.ByteArrayOutputStream;
  import java.util.ArrayList;
  import java.util.Arrays;
  
  import android.content.Context;
  import android.content.SharedPreferences;
  import android.graphics.Bitmap;
  import android.graphics.Canvas;
  import android.graphics.DashPathEffect;
  import android.graphics.ImageFormat;
  import android.graphics.Matrix;
  import android.graphics.Paint;
  import android.graphics.Point;
  import android.graphics.PointF;
  import android.graphics.Rect;
  import android.os.AsyncTask;
  import android.os.Handler;
  import android.preference.PreferenceManager;
  import android.util.Log;
  import android.view.Display;
  import android.view.View;
  import android.view.WindowManager;
  
  import com.almalence.SwapHeap;
  import com.almalence.plugins.capture.expobracketing.ExpoBracketingCapturePlugin;
  import com.almalence.plugins.processing.groupshot.GroupShotCore;
  import com.almalence.util.ImageConversion;
  import com.almalence.util.Size;
  
  /* <!-- +++
  import com.almalence.opencam_plus.cameracontroller.CameraController;
  import com.almalence.opencam_plus.ApplicationScreen;
  import com.almalence.opencam_plus.PluginManager;
  +++ --> */
  //<!-- -+-
  import com.almalence.opencam.cameracontroller.CameraController;
  import com.almalence.opencam.ApplicationScreen;
  import com.almalence.opencam.PluginManager;
  //-+- -->
  
  import com.almalence.plugins.processing.multishot.AlmaCLRShot;
  
  public class SequenceCore
  {
  	private final String				TAG							= this.getClass()
  																			.getName()
  																			.substring(this.getClass().getName().lastIndexOf(".") + 1);
  	
  	
  	private static int					mSensitivity	= 22;
  	private static int					mMinSize		= 1000;
  	private static String				mGhosting		= "0";
  
  	private Handler						mHandler		= null;
  	
  	private int							mImageDataOrientation;
  	private boolean						mCameraMirrored;
  	public static int					mDisplayWidth;
  	public static int					mDisplayHeight;
  	
  	public int							imagesAmount	 = 0;
  
  	private AlmaCLRShot					mAlmaCLRShot;
  	private int[]						indexes;
  	
  	private ArrayList<Integer>			mYUVBufferList;	// List of input images.
  
  	public void setYUVBufferList(ArrayList<Integer> YUVBufferList)
  	{
  		this.mYUVBufferList = YUVBufferList;
  	}
  	
  	public ArrayList<Integer> getYUVBufferList()
  	{
  		return mYUVBufferList;
  	}
  	
  	private SequenceCore()
  	{
  		super();
  	}
  	
  	private static SequenceCore	mInstance;
  	
  	public static SequenceCore getInstance()
  	{
  		if (mInstance == null)
  		{
  			mInstance = new SequenceCore();
  		}
  		return mInstance;
  	}
  	
  	public void initializeParameters(int imgAmount, boolean mirrored, int imageDataOrientation, Handler handler)
  	{
  		imagesAmount = imgAmount;
  		mCameraMirrored = mirrored;
  		mImageDataOrientation = imageDataOrientation;
  		mHandler = handler;
  	}
  	
  	public void release()
  	{
  		mAlmaCLRShot.release();
  	}
  	
  	public void onStartProcessing()
  	{
  		CameraController.Size imageSize = CameraController.getCameraImageSize();
  		Size input = new Size(imageSize.getWidth(), imageSize.getHeight());
  		int minSize = 1000;
  		if (mMinSize == 0)
  		{
  			minSize = 0;
  		} else
  		{
  			minSize = input.getWidth() * input.getHeight() / mMinSize;
  		}
  		
  		int iImageWidth = imageSize.getWidth();
  		int iImageHeight = imageSize.getHeight();
  		
  		mAlmaCLRShot = AlmaCLRShot.getInstance();
  		
  		Display display = ((WindowManager) ApplicationScreen.instance.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
  		Point dis = new Point();
  		display.getSize(dis);
  
  		float imageRatio = (float) iImageWidth / (float) iImageHeight;
  		float displayRatio = (float) dis.y / (float) dis.x;
  
  		if (imageRatio > displayRatio)
  		{
  			mDisplayWidth = dis.y;
  			mDisplayHeight = (int) ((float) dis.y / (float) imageRatio);
  		} else
  		{
  			mDisplayWidth = (int) ((float) dis.x * (float) imageRatio);
  			mDisplayHeight = dis.x;
  		}
  
  		Size preview = new Size(mDisplayWidth, mDisplayHeight);			
  
  		this.indexes = new int[imagesAmount];
  		for (int i = 0; i < imagesAmount; i++)
  		{
  			this.indexes[i] = i;
  		}
  
  		try
  		{
  			// frames!!! should be taken from heap
  			mAlmaCLRShot.addInputFrame(mYUVBufferList, input);
  	
  			mAlmaCLRShot.initialize(preview,
  					0, //Angle
  					0, //Base frame
  			/*
  			 * sensitivity for objection detection
  			 */
  			mSensitivity - 15,
  			/*
  			 * Minimum size of object to be able to detect -15 ~ 15 max -> easy
  			 * detection dull detection min ->
  			 */
  			minSize,
  			/*
  			 * ghosting parameter 0 : normal operation 1 : detect ghosted
  			 * objects but not remove them 2 : detect and remove all object
  			 */
  			Integer.parseInt(mGhosting), indexes, null);
  		} catch (Exception e)
  		{
  			e.printStackTrace();
  		}
  	}
  	
  	public Bitmap getPreviewBitmap()
  	{
  		return mAlmaCLRShot.getPreviewBitmap();
  	}
  	
  	public void runProcessingTask(int[] idx)
  	{
  		ProcessingTask task = new ProcessingTask();
  		task.idxInput = idx;
  		task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
  	}
  
  	private class ProcessingTask extends AsyncTask<Void, Void, Void>
  	{
  		public int[] idxInput;
  
  		@Override
  		protected void onPreExecute()
  		{
  			SequenceProcessingPlugin.setProgressBarVisibility(true);
  		}
  		
  		@Override
  		protected Void doInBackground(Void... params)
  		{
  			android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DEFAULT);
  			CameraController.Size imageSize = CameraController.getCameraImageSize();
  			Size input = new Size(imageSize.getWidth(), imageSize.getHeight());
  			int minSize = 1000;
  			if (mMinSize == 0)
  			{
  				minSize = 0;
  			} else
  			{
  				minSize = input.getWidth() * input.getHeight() / mMinSize;
  			}
  
  			Size preview = new Size(mDisplayWidth, mDisplayHeight);
  			try
  			{
  				
  				
  				mAlmaCLRShot.initialize(preview,
  						0, //Angle
  						0, //Base frame
  				/*
  				 * sensitivity for objection detection
  				 */
  				mSensitivity - 15,
  				/*
  				 * Minimum size of object to be able to detect -15 ~ 15 max -> easy
  				 * detection dull detection min ->
  				 */
  				minSize,
  				/*
  				 * ghosting parameter 0 : normal operation 1 : detect ghosted
  				 * objects but not remove them 2 : detect and remove all object
  				 */
  				Integer.parseInt(mGhosting), idxInput, null);
  			} catch (NumberFormatException e)
  			{
  				e.printStackTrace();
  			} catch (Exception e)
  			{
  				e.printStackTrace();
  			}
  
  			return null;
  		}
  		
  		@Override
  		protected void onPostExecute(Void result)
  		{
  			SequenceProcessingPlugin.setProgressBarVisibility(false);
  			mHandler.sendEmptyMessage(SequenceProcessingPlugin.MSG_REDRAW);
  		}
  	}
  	
  	public void processAndSaveData(long sessionID)
  	{
  		byte[] result = mAlmaCLRShot.processingSaveData();
  		int frame_len = result.length;
  		int frame = SwapHeap.SwapToHeap(result);
  
  		PluginManager.getInstance().addToSharedMem("resultframeformat1" + sessionID, "jpeg");
  		PluginManager.getInstance().addToSharedMem("resultframe1" + sessionID, String.valueOf(frame));
  		PluginManager.getInstance().addToSharedMem("resultframelen1" + sessionID, String.valueOf(frame_len));
  
  		//Nexus 6 and 6p has a original front camera sensor orientation, we have to manage it
  		PluginManager.getInstance().addToSharedMem("resultframeorientation1" + sessionID, String.valueOf(mImageDataOrientation));
  //				String.valueOf((CameraController.isFlippedSensorDevice() && mCameraMirrored)? (mImageDataOrientation + 180) % 360 : mImageDataOrientation));
  		PluginManager.getInstance().addToSharedMem("resultframemirrored1" + sessionID, String.valueOf(mCameraMirrored));
  
  		PluginManager.getInstance().addToSharedMem("amountofresultframes" + sessionID, String.valueOf(1));
  
  		PluginManager.getInstance().addToSharedMem("sessionID", String.valueOf(sessionID));
  		mAlmaCLRShot.release();
  	}
  }
  