package freed.gl;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.TextureView;
import android.widget.FrameLayout;

import freed.cam.histogram.HistogramController;
import freed.gl.program.compute.FocusPeakComputeProgram;
import freed.utils.Log;

public class GLPreview extends GLSurfaceView {
    private static final String TAG =  GLPreview.class.getSimpleName();
    MainRenderer mRenderer;
    private TextureView.SurfaceTextureListener surfaceTextureListener;
    private boolean focuspeak_enabled = false;
    private boolean zebra_enabled= false;
    private HistogramController histogramController;

    public enum PreviewProcessors
    {
        Normal,
        FocusPeak,
        Zebra,
        FocusPeak_Zebra,
    }

    public GLPreview(Context context) {
        super(context);
        init();
    }

    public GLPreview(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public void setHistogramController(HistogramController histogramController) {
        this.histogramController = histogramController;
    }

    public HistogramController getHistogramController() {
        return histogramController;
    }

    private void init() {
        mRenderer = new MainRenderer(this);
        setEGLContextClientVersion(3);
        setRenderer(mRenderer);
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }

    public void fireOnSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int w, int h)
    {
        if (surfaceTextureListener != null)
            surfaceTextureListener.onSurfaceTextureAvailable(surfaceTexture,w,h);
    }

    public void fireOnSurfaceTextureDestroyed(SurfaceTexture surfaceTexture)
    {
        if (surfaceTextureListener != null)
            surfaceTextureListener.onSurfaceTextureDestroyed(surfaceTexture);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        super.surfaceCreated(holder);
        mRenderer.setSize(holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
        Log.d(TAG, "texSize :" + holder.getSurfaceFrame().width() +"/"+ holder.getSurfaceFrame().height());

    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        super.surfaceDestroyed(holder);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        super.surfaceChanged(holder, format, w, h);
        mRenderer.setSize(holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
        Log.d(TAG, "texSize :" + holder.getSurfaceFrame().width() +"/"+ holder.getSurfaceFrame().height());
        if (surfaceTextureListener != null)
            surfaceTextureListener.onSurfaceTextureSizeChanged(mRenderer.getmSTexture(),w,h);
    }

    @Override
    public void onResume() {
        super.onResume();
        //mRenderer.onResume();
    }

    @Override
    public void onPause() {
        fireOnSurfaceTextureDestroyed(getSurfaceTexture());
        //mRenderer.onPause();
        super.onPause();
    }


    public SurfaceTexture getSurfaceTexture()
    {
        return mRenderer.getmSTexture();
    }


    public void setSurfaceTextureListener(TextureView.SurfaceTextureListener l) {
        this.surfaceTextureListener = l;
    }

    public void scale(int in_width, int in_height, int out_width, int out_height,boolean switchAspect)
    {
        //in w:1440 in h: 1080 out w: 2400 out h: 1080
        //in w:1440 in h: 1080 out w: 2560 out h: 1440
        Log.d(TAG, "in w: " + in_width + " in h: " + in_height + " out w: " + out_width + " out h: " + out_height);
        FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(in_width, in_height);


        if (!switchAspect) {

            if (in_height >= out_height) {
                layout.height = in_height;
                layout.width = in_width;
                layout.leftMargin = (out_width - in_width) / 2;
                layout.rightMargin = layout.leftMargin;
            }
            else {
                layout.height = Math.round((float) in_height * ((float) out_height / (float) in_height));
                layout.width = Math.round((float) in_width * ((float) out_height / (float) in_height));
                layout.leftMargin = (out_width - layout.width) / 2;
                layout.rightMargin = layout.leftMargin;
            }
        }
        else {
            int s = out_height - in_width;
            int ws = out_width +s;
            int hs = out_height - s;
            layout.height = ws;
            layout.width = hs;
            layout.leftMargin = (out_width - hs) / 2;
            layout.rightMargin = layout.leftMargin;
        }

        this.post(()-> this.setLayoutParams(layout));
    }

    public void setOrientation(int or)
    {
        mRenderer.getPreviewProgram().setOrientation(or);
    }

    public void setPreviewProcessors(PreviewProcessors processors)
    {
        mRenderer.setProgram(processors);
    }

    public void setFocusPeakColor(FocusPeakComputeProgram.Colors color)
    {
        mRenderer.getFocuspeakProgram().setPeak_color(color);
        requestRender();
    }

    public void setRed(boolean r)
    {
        mRenderer.getFocuspeakProgram().setRed(r);
        requestRender();
    }

    public void setGreen(boolean g)
    {
        mRenderer.getFocuspeakProgram().setGreen(g);
        requestRender();
    }

    public void setBlue(boolean b)
    {
        mRenderer.getFocuspeakProgram().setBlue(b);
        requestRender();
    }

    public void setFocuspeak_enabled(boolean focuspeak_enabled) {
        this.focuspeak_enabled = focuspeak_enabled;
        applyProgram();
    }

    public boolean isFocuspeak_enabled() {
        return focuspeak_enabled;
    }

    public void setZebra_enabled(boolean zebra_enabled) {
        this.zebra_enabled = zebra_enabled;
        applyProgram();
    }

    public boolean isZebra_enabled() {
        return zebra_enabled;
    }

    private void applyProgram()
    {
        if (zebra_enabled && focuspeak_enabled)
            setPreviewProcessors(PreviewProcessors.FocusPeak_Zebra);
        else if (zebra_enabled)
            setPreviewProcessors(PreviewProcessors.Zebra);
        else if (focuspeak_enabled)
        {
            setPreviewProcessors(PreviewProcessors.FocusPeak);
        }
        else
            setPreviewProcessors(PreviewProcessors.Normal);
    }

    public void setZebraHight(float high)
    {
        mRenderer.getClippingProgram().setZebra_high(high);
    }

    public void setZebraLow(float low)
    {
                mRenderer.getClippingProgram().setZebra_low(low);
    }

    public void setColorWaveForm(boolean on)
    {
        mRenderer.getWaveFormRGBProgram().setColorWaveForm(on);
    }

    public boolean isColorWaveForm()
    {
        return true;
    }
}
