package freed.image;

import android.location.Location;
import android.media.Image;
import android.os.Build;
import android.os.ParcelFileDescriptor;

import androidx.annotation.RequiresApi;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import freed.FreedApplication;
import freed.cam.apis.basecamera.modules.ModuleInterface;
import freed.dng.DngProfile;
import freed.file.FileListController;
import freed.file.holder.BaseHolder;
import freed.file.holder.FileHolder;
import freed.file.holder.UriHolder;
import freed.jni.ExifInfo;
import freed.jni.GpsInfo;
import freed.jni.OpCode;
import freed.jni.RawToDng;
import freed.settings.SettingsManager;
import freed.utils.Log;

/**
 * Created by KillerInk on 13.11.2017.
 */

public class ImageSaveTask extends ImageTask
{
    private final String TAG = ImageSaveTask.class.getSimpleName();

    public final static int JPEG = 0;
    public final static int RAW10 = 1;
    public final static int RAW12 = 2;
    public final static int RAW_SENSOR = 3;
    public final static int DUMP_RAWDATA = 4;


    private byte[] bytesTosave;
    private int imageFormat = JPEG;
    private DngProfile profile;
    private File filename;
    private boolean externalSD;
    private int orientation = 0;
    private Location location;
    private boolean forceRawToDng = false;

    private float fnum, focal = 0;
    private int mISO;
    private float exposureTime;
    private int flash = 0;
    private float expoindex;
    private String whitebalance;
    private final ModuleInterface moduleInterface;

    private OpCode opcode;
    private float baselineExposure = 0;
    private final float baselineExposureOffset = 0;
    private int greensplit = 0;
    private final SettingsManager settingsManager;
    private final FileListController fileListController;
    private Image image;
    private int crop_width, crop_height;


    public ImageSaveTask(ModuleInterface moduleInterface)
    {
        this.moduleInterface = moduleInterface;
        settingsManager = FreedApplication.settingsManager();
        fileListController = FreedApplication.fileListController();
    }


    public void clear()
    {
        this.whitebalance = null;
        this.location =null;
        this.filename = null;
        this.profile = null;
        this.bytesTosave = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (image != null)
            {
                image.close();
            }
        }
    }

    public void setBytesTosave(byte[] bytes, int imageFormat)
    {
        this.bytesTosave = bytes;
        this.imageFormat = imageFormat;
    }

    public void setByteBufferTosave(Image buffer, int imageFormat)
    {
        this.image = buffer;
        this.imageFormat = imageFormat;
    }

    public void setDngProfile(DngProfile profile)
    {
        this.profile = profile;
    }

    public void setFilePath(File file, boolean externalSD)
    {
        this.filename = file;
        this.externalSD =externalSD;
    }

    public void setOrientation(int orientation)
    {
        this.orientation = orientation;
    }

    public void setLocation(Location location)
    {
        this.location = location;
    }

    public void setForceRawToDng(boolean forceRawToDng)
    {
        this.forceRawToDng =forceRawToDng;
    }

    public void setFnum(float fnum)
    {
        this.fnum = fnum;
    }

    public void setFocal(float focal)
    {
        this.focal = focal;
    }

    public void setIso(int iso)
    {
        this.mISO = iso;
    }

    public void setExposureTime(float exposureTime)
    {
        this.exposureTime = exposureTime;
    }

    public void setFlash(int flash)
    {
        this.flash = flash;
    }

    public void setExposureIndex(float expoindex)
    {
        this.expoindex = expoindex;
    }

    public void setWhiteBalance(String wb)
    {
        this.whitebalance = wb;
    }

    public void setOpCode(OpCode opCode){
        this.opcode = opCode;
    }

    public void setBaselineExposure(float baselineExposure)
    {
        this.baselineExposure = baselineExposure;
    }

    public void setBayerGreenSplit(int greenSplit)
    {
        this.greensplit = greenSplit;
    }

    public void setCrop_WidthHeight(int width,int height)
    {
        this.crop_width = width;
        this.crop_height = height;
    }

    @Override
    public boolean process()
    {
        if(imageFormat == RAW10 || (imageFormat == RAW_SENSOR && forceRawToDng)){
            Log.d(TAG, "saveRawToDng");
            saveRawToDng();
            clear();
            return true;
        }
        else if (imageFormat == JPEG) {
            Log.d(TAG, "saveJpeg");
            saveJpeg();
            clear();
            return true;
        }
        else if (imageFormat == DUMP_RAWDATA){
            saveJpeg();
            clear();
        }
        Log.d(TAG,"Save done");
        return false;
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void saveRawToDng()
    {
        RawToDng rawToDng = RawToDng.GetInstance();
        ParcelFileDescriptor pfd = null;
        if (location != null)
        {
            GpsInfo gpsInfo = new GpsInfo(location);
            rawToDng.SetGpsData(gpsInfo.getByteBuffer());
        }
        ExifInfo info = new ExifInfo(mISO,flash,exposureTime,focal,fnum,expoindex,"",orientation+"");
        rawToDng.setExifData(info);
//        if (whitebalance != null)
//            rawToDng.SetWBCT(whitebalance);
        if (settingsManager.getOpCode() != null)
            rawToDng.setOpCode(settingsManager.getOpCode());
        else if (opcode != null)
            rawToDng.setOpCode(opcode);

        rawToDng.setBaselineExposure(baselineExposure);
        rawToDng.setBaselineExposureOffset(baselineExposureOffset);
        rawToDng.setBayerGreenSplit(greensplit);
        rawToDng.setCropWidthHeight(crop_width,crop_height);
        BaseHolder fileholder = fileListController.getNewImgFileHolder(filename);
        if (fileholder instanceof FileHolder) {
            rawToDng.setBayerData(bytesTosave, filename.getAbsolutePath());
        }
        else if(fileholder instanceof UriHolder) {
            try {
                pfd = ((UriHolder)fileholder).getParcelFileDescriptor();
                if (bytesTosave != null)
                    rawToDng.SetBayerDataFD(bytesTosave, pfd, filename.getName());
                else
                    rawToDng.SetBayerDataBufFD(image.getPlanes()[0].getBuffer(), pfd, filename.getName());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        rawToDng.WriteDngWithProfile(profile);
        if (image != null)
        {
            image.close();
        }
        moduleInterface.internalFireOnWorkDone(fileholder);
    }

    private void saveJpeg()
    {
        Log.d(TAG, "Start Saving Bytes");
        BaseHolder fileholder = fileListController.getNewImgFileHolder(filename);
        try {
            BufferedOutputStream outStream = new BufferedOutputStream(fileholder.getOutputStream());
            outStream.write(bytesTosave);
            outStream.flush();
            outStream.close();
        } catch (IOException e) {
            Log.WriteEx(e);
        }
        if (fileholder != null)
            moduleInterface.internalFireOnWorkDone(fileholder);
        Log.d(TAG, "End Saving Bytes");
    }



}
