package freed.cam.apis.basecamera.parameters.ae;

import freed.cam.apis.basecamera.CameraWrapperInterface;
import freed.cam.apis.basecamera.parameters.AbstractParameter;
import freed.settings.SettingKeys;
import freed.utils.Log;

/**
 * Created by KillerInk on 29.12.2017.
 */

public abstract class AeManager<C extends CameraWrapperInterface> implements AeManagerInterface
{
    protected C cameraWrapperInterface;
    protected ManualIso manualIso;
    protected ManualExposureTime manualExposureTime;
    protected ExposureCompensation exposureCompensation;
    protected AeStates activeAeState = AeStates.auto;

    public AeManager(C cameraWrapperInterface)
    {
        this.cameraWrapperInterface =cameraWrapperInterface;
        manualIso = new ManualIso(cameraWrapperInterface);
        manualExposureTime = new ManualExposureTime(cameraWrapperInterface);
        exposureCompensation =new ExposureCompensation(cameraWrapperInterface);
    }

    public AbstractParameter getIso()
    {
        return manualIso;
    }

    public AbstractParameter getExposureTime()
    {
        return manualExposureTime;
    }

    public AbstractParameter getExposureCompensation()
    {
        return exposureCompensation;
    }

    @Override
    public abstract void setExposureTime(int valueToSet, boolean setToCamera);

    @Override
    public abstract void setIso(int valueToSet, boolean setToCamera);

    @Override
    public abstract void setExposureCompensation(int valueToSet, boolean setToCamera);

    @Override
    public abstract void setAeMode(AeStates aeState);

    @Override
    public AeStates getActiveAeState() {
        return activeAeState;
    }

    @Override
    public boolean isExposureCompensationWriteable() {
        return activeAeState == AeStates.iso_priority || activeAeState == AeStates.shutter_priority || activeAeState == AeStates.auto;
    }

    @Override
    public boolean isExposureTimeWriteable() {
        return activeAeState == AeStates.shutter_priority || activeAeState == AeStates.manual;
    }

    @Override
    public boolean isIsoWriteable() {
        return activeAeState == AeStates.iso_priority || activeAeState == AeStates.manual || activeAeState == AeStates.auto;
    }

    public class ManualExposureTime extends AbstractParameter
    {
        public final String TAG = ManualExposureTime.class.getSimpleName();
        public ManualExposureTime(CameraWrapperInterface cameraUiWrapper) {
            super(cameraUiWrapper,SettingKeys.M_EXPOSURE_TIME);
        }

        @Override
        public int getIntValue()
        {
            return currentInt;
        }



        @Override
        public String[] getStringValues() {
            return stringvalues;
        }

        @Override
        public void setValue(int valueToSet, boolean setToCamera)
        {
            super.setValue(valueToSet,setToCamera);
            setExposureTime(valueToSet,setToCamera);
        }

        @Override
        public ViewState getViewState() {
            if (isExposureTimeWriteable())
                return ViewState.Enabled;
            else
                return ViewState.Disabled;
        }

    }


    public class ManualIso extends AbstractParameter
    {
        final String TAG = ManualIso.class.getSimpleName();
        public ManualIso(CameraWrapperInterface cameraUiWrapper) {
            super(cameraUiWrapper,SettingKeys.M_MANUAL_ISO);
            currentInt = 0;
        }

        @Override
        public void setValue(int valueToSet, boolean setToCamera)
        {
            super.setValue(valueToSet,setToCamera);
            //workaround when value was -1 to avoid outofarray ex
            Log.d(TAG, "set Manual Iso: " +valueToSet);
            if (valueToSet == -1)
                valueToSet = 0;
            //////////////////////
            setIso(valueToSet,setToCamera);
        }

        @Override
        public ViewState getViewState() {
            if (isIsoWriteable())
                return ViewState.Enabled;
            else
                return ViewState.Disabled;
        }
    }

    public class ExposureCompensation extends AbstractParameter
    {
        final String TAG = ExposureCompensation.class.getSimpleName();

        public ExposureCompensation(CameraWrapperInterface cameraUiWrapper) {
            super(cameraUiWrapper,SettingKeys.M_EXPOSURE_COMPENSATION);
            currentInt = stringvalues.length / 2;
        }



        @Override
        public int getIntValue() {
            return super.getIntValue();
        }

        @Override
        public String getStringValue() {
            if (currentInt > stringvalues.length)
                currentInt = stringvalues.length/2;
            try {
                return stringvalues[currentInt];
            }
            catch (NullPointerException e)
            {
                return "0";
            }
        }

        @Override
        public void setValue(int valueToSet, boolean setToCamera) {
            if (valueToSet >= stringvalues.length)
                valueToSet = stringvalues.length/2;
            super.setValue(valueToSet,setToCamera);
            currentInt = valueToSet;
            setExposureCompensation(valueToSet - stringvalues.length/2,setToCamera);
            fireStringValueChanged(stringvalues[valueToSet]);
        }

        @Override
        public ViewState getViewState() {
            if (isExposureCompensationWriteable())
                return ViewState.Enabled;
            else
                return ViewState.Disabled;
        }
    }

}
