using NodeCanvas.Framework;
using ParadoxNotion.Design;
using Reset.Core;
using Unity.Cinemachine;
using UnityEditor;
using UnityEngine;

namespace NodeCanvas.Tasks.Actions {
	[Category("Reset")]
	[Description("Change Cinemachine camera settings for the player")]
	public class ChangeCameraSettings : ActionTask{
		[ParadoxNotion.Design.Header("Main Settings")]
		public FloatValueGroup fieldOfView = new (newLabel: "FOV");

		[ParadoxNotion.Design.Header("Orbit Follow Ring Settings"), Space (5)]
		public Vector3ValueGroup orbitTargetOffset = new(newLabel: "Target Offset");
		[Space(5)]public Vector3ValueGroup orbitPositionDamping = new(newLabel: "Position Damping");
		
		public OrbitalFollowValueGroup orbitFollowTop = new (newLabel: "Top");
		public OrbitalFollowValueGroup orbitFollowCenter = new (newLabel: "Center");
		public OrbitalFollowValueGroup orbitFollowBottom = new (newLabel: "Bottom");

		public BoolValueGroup enableXAxis = new (newLabel: "Input Axis X Enabled");
		public BoolValueGroup enableYAxis = new (newLabel: "Input Axis Y Enabled");
		
		public FloatValueGroup axisLookXGain = new (newLabel: "Look Orbit X Gain");
		public FloatValueGroup axisLookYGain = new (newLabel: "Look Orbit Y Gain");
		
		[ParadoxNotion.Design.Header("Rotation Composer Settings")]
		public Vector2ValueGroup screenPosition = new (newLabel: "Screen Position");
		
		[ParadoxNotion.Design.Header("Camera Offset Settings")]
		public Vector3ValueGroup cameraOffset = new (newLabel: "Offset");
		
		//Use for initialization. This is called only once in the lifetime of the task.
		//Return null if init was successfull. Return an error string otherwise
		protected override string OnInit(){
			return null;
		}

		//This is called once each time the task is enabled.
		//Call EndAction() to mark the action as finished, either in success or failure.
		//EndAction can be called from anywhere.
		protected override void OnExecute(){
			UpdateOrbitFollowValue(orbitFollowTop, ref CameraSettingsProcessor.values.orbitFollowTopHeight, ref CameraSettingsProcessor.values.orbitFollowTopRadius);
			UpdateOrbitFollowValue(orbitFollowCenter, ref CameraSettingsProcessor.values.orbitFollowCenterHeight, ref CameraSettingsProcessor.values.orbitFollowCenterRadius);
			UpdateOrbitFollowValue(orbitFollowBottom, ref CameraSettingsProcessor.values.orbitFollowBottomHeight, ref CameraSettingsProcessor.values.orbitFollowBottomRadius);
			
			UpdateVector3Value(cameraOffset, ref CameraSettingsProcessor.values.cameraOffsetOffset);
			
			UpdateVector3Value(orbitPositionDamping, ref CameraSettingsProcessor.values.orbitPositionDamping);
			UpdateVector3Value(orbitTargetOffset, ref CameraSettingsProcessor.values.orbitTargetOffset);
			
			UpdateVector2Value(screenPosition, ref CameraSettingsProcessor.values.rotationComposerScreenPos);
			UpdateFloatValue(fieldOfView, ref CameraSettingsProcessor.values.mainFieldOfView);
			
			UpdateFloatValue(axisLookXGain, ref CameraSettingsProcessor.values.axisLookGainX);
			UpdateFloatValue(axisLookYGain, ref CameraSettingsProcessor.values.axisLookGainY);
			
			UpdateBoolValue(enableXAxis, ref CameraSettingsProcessor.values.axisLookEnabledX);
			UpdateBoolValue(enableYAxis, ref CameraSettingsProcessor.values.axisLookEnabledY);
			
			
			EndAction(true);
		}

		public void UpdateVector3Value(Vector3ValueGroup valueGroup, ref CameraSettingSingleValue<Vector3> targetProperty){
			switch (valueGroup.changeX) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue.x = valueGroup.newValue.x;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue.x = targetProperty.originalValue.x;
					break;
			}
			
			switch (valueGroup.changeY) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue.y = valueGroup.newValue.y;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue.y = targetProperty.originalValue.y;
					break;
			}
			
			switch (valueGroup.changeZ) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue.z = valueGroup.newValue.z;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue.z = targetProperty.originalValue.z;
					break;
			}
		}
		
		public void UpdateVector2Value(Vector2ValueGroup valueGroup, ref CameraSettingSingleValue<Vector2> targetProperty){
			switch (valueGroup.changeX) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue.x = valueGroup.newValue.x;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue.x = targetProperty.originalValue.x;
					break;
			}
			
			switch (valueGroup.changeY) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue.y = valueGroup.newValue.y;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue.y = targetProperty.originalValue.y;
					break;
			}
		}
		
		public void UpdateOrbitFollowValue(OrbitalFollowValueGroup valueGroup, ref CameraSettingSingleValue<float> targetHeight, ref CameraSettingSingleValue<float> targetRadius){
			switch (valueGroup.changeHeight) {
				case ValueChangeAction.NewValue:
					targetHeight.targetValue = valueGroup.height;
					break;
				case ValueChangeAction.ResetValue:
					targetHeight.targetValue = targetHeight.originalValue;
					break;
			}
			
			switch (valueGroup.changeRadius) {
				case ValueChangeAction.NewValue:
					targetRadius.targetValue = valueGroup.radius;
					break;
				case ValueChangeAction.ResetValue:
					targetRadius.targetValue = targetRadius.originalValue;
					break;
			}
		}
		
		public void UpdateBoolValue(BoolValueGroup valueGroup, ref CameraSettingSingleValue<bool> targetProperty){
			switch (valueGroup.changeValue) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue = valueGroup.value;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue = targetProperty.originalValue;
					break;
			}
		}
		
		public void UpdateFloatValue(FloatValueGroup valueGroup, ref CameraSettingSingleValue<float> targetProperty){
			switch (valueGroup.changeValue) {
				case ValueChangeAction.NewValue:
					targetProperty.targetValue = valueGroup.value.value;
					break;
				case ValueChangeAction.ResetValue:
					targetProperty.targetValue = targetProperty.originalValue;
					break;
			}
		}

		//Called once per frame while the action is active.
		protected override void OnUpdate() {
			
		}

		//Called when the task is disabled.
		protected override void OnStop() {
			
		}

		//Called when the task is paused.
		protected override void OnPause() {
			
		}
	}
}