context: using InfernalRobotics.Command;
  using InfernalRobotics.Control;
  using KSP.IO;
  using KSP.UI.Screens;
  using KSP.UI;
  using System;
  using System.Linq;
  using System.Reflection;
  using System.Collections.Generic;
  using UnityEngine;
  using UnityEngine.UI;
  using UnityEngine.EventSystems;
  
  namespace InfernalRobotics.Gui
  {
      [KSPAddon(KSPAddon.Startup.Flight, false)]
      public class IRFlightWindowManager : WindowManager
      {
          public override string AddonName { get { return this.name; } }
      }
  
      [KSPAddon(KSPAddon.Startup.EditorAny, false)]
      public class IREditorWindowManager : WindowManager
      {
          public override string AddonName { get { return this.name; } }
      }
  
      public class WindowManager : MonoBehaviour
      {
          public virtual String AddonName { get; set; }
  
          private static WindowManager _instance;
          private static GameObject _controlWindow;
          private static GameObject _settingsWindow;
          private static GameObject _editorWindow;
          private static GameObject _presetsWindow;
          private static IServo presetWindowServo;
  
          private static CanvasGroupFader _controlWindowFader;
          private static CanvasGroupFader _editorWindowFader;
          private static CanvasGroupFader _settingsWindowFader;
          private static CanvasGroupFader _presetsWindowFader;
  
          internal static Dictionary<ServoController.ControlGroup,GameObject> _servoGroupUIControls;
          internal static Dictionary<IServo, GameObject> _servoUIControls;
  
          public static float _UIAlphaValue = 0.8f;
          public static float _UIScaleValue = 1.0f;
          private const float UI_FADE_TIME = 0.1f;
          private const float UI_MIN_ALPHA = 0.2f;
          private const float UI_MIN_SCALE = 0.5f;
          private const float UI_MAX_SCALE = 2.0f;
  
          internal static bool guiRebuildPending = false;
          private ApplicationLauncherButton appLauncherButton;
          private static Texture2D appLauncherButtonTexture;
          public static bool useBlizzyToolbar = false;
          public static BlizzyToolbar.IButton blizzyButton;
  
          private bool guiFlightEditorWindowOpen;
          private bool guiFlightPresetModeOn;
          private bool guiPresetsWindowOpen;
          private bool guiHidden;
  
          internal static Color ir_yellow = new Color(255, 194, 0, 255);
  
          private static Vector3 _controlWindowPosition;
          private static Vector3 _editorWindowPosition;
          private static Vector3 _settingsWindowPosition;
          private static Vector3 _presetsWindowPosition;
  
          private static Vector2 _editorWindowSize;
  
          public static bool UseElectricCharge = true;
  
          public bool GUIEnabled = false;
  
          private static bool isKeyboardLocked = false;
  
          public static WindowManager Instance
          {
              get { return _instance; }
          }
  
          private void Awake()
          {
              
              LoadConfigXml();
  
              Logger.Log("[NewGUI] awake, Mode: " + AddonName);
              guiFlightEditorWindowOpen = false;
  
              GameScenes scene = HighLogic.LoadedScene;
  
              if (scene == GameScenes.FLIGHT || scene == GameScenes.EDITOR)
              {
                  _instance = this;
  
                  _servoGroupUIControls = new Dictionary<ServoController.ControlGroup, GameObject>();
                  _servoUIControls = new Dictionary<IServo, GameObject>();
              }
              else
              {
                  _instance = null;
                  //actually we don't need to go further if it's not flight or editor
                  return;
              }
  
              if (BlizzyToolbar.ToolbarManager.ToolbarAvailable)
              {
                  blizzyButton = BlizzyToolbar.ToolbarManager.Instance.add("sirkut", "IRButton");
                  blizzyButton.TexturePath = "MagicSmokeIndustries/blizzy_icon";
                  blizzyButton.ToolTip = "Infernal Robotics";
                  blizzyButton.Visibility = new BlizzyToolbar.GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT);
                  blizzyButton.OnClick += e => { if (GUIEnabled) HideIRWindow(); else ShowIRWindow(); };
                  blizzyButton.Visible = useBlizzyToolbar;
              }
  
              GameEvents.onGameSceneLoadRequested.Add(OnGameSceneLoadRequestedForAppLauncher);
              GameEvents.onGUIApplicationLauncherReady.Add (AddAppLauncherButton);
  
              Logger.Log("[GUI] Added Toolbar GameEvents Handlers", Logger.Level.Debug);
  
              GameEvents.onShowUI.Add(OnShowUI);
              GameEvents.onHideUI.Add(OnHideUI);
  
              Logger.Log("[GUI] awake finished successfully", Logger.Level.Debug);
          }
  
          private void OnShowUI()
          {
              guiHidden = false;
              /*
              if (_controlWindowFader)
              {
                  _controlWindowFader.FadeTo(_UIAlphaValue, 0.1f);
              }
              if (_editorWindowFader)
              {
                  _editorWindowFader.FadeTo(_UIAlphaValue, 0.1f);
              }
              if (_uiSettingsWindowFader)
              {
                  _uiSettingsWindowFader.FadeTo(_UIAlphaValue, 0.1f);
              }
              if (_presetsWindowFader)
              {
                  _presetsWindowFader.FadeTo(_UIAlphaValue, 0.1f);
              }*/
          }
  
          private void OnHideUI()
          {
              guiHidden = true;
              /*
              if(_controlWindowFader)
              {
                  _controlWindowFader.FadeTo(0f, 0.1f);
              }
              if(_editorWindowFader)
              {
                  _editorWindowFader.FadeTo(0f, 0.1f);
              }
              if(_uiSettingsWindowFader)
              {
                  _uiSettingsWindowFader.FadeTo(0f, 0.1f);
              }
              if(_presetsWindowFader)
              {
                  _presetsWindowFader.FadeTo(0f, 0.1f);
              }*/
          }
  
          private void InitSettingsWindow()
          {
              if (_settingsWindow != null)
                  return;
  
              _settingsWindow = GameObject.Instantiate(UIAssetsLoader.uiSettingsWindowPrefab);
              _settingsWindow.transform.SetParent(UIMasterController.Instance.appCanvas.transform, false);
              _settingsWindow.GetChild("WindowTitle").AddComponent<PanelDragger>();
              _settingsWindowFader = _settingsWindow.AddComponent<CanvasGroupFader>();
  
              if (_settingsWindowPosition == Vector3.zero)
              {
                  //get the default position from the prefab
                  _settingsWindowPosition = _settingsWindow.transform.position;
              }
              else
              {
                  _settingsWindow.transform.position = ClampWindowPosition(_settingsWindowPosition);
              }
  
              _settingsWindow.GetComponent<CanvasGroup>().alpha = 0f;
  
              var closeButton = _settingsWindow.GetChild("WindowTitle").GetChild("RightWindowButton");
              if (closeButton != null)
              {
                  closeButton.GetComponent<Button>().onClick.AddListener(ToggleSettingsWindow);
              }
  
              var alphaText = _settingsWindow.GetChild("WindowContent").GetChild("UITransparencySliderHLG").GetChild("TransparencyValue").GetComponent<Text>();
              alphaText.text = string.Format("{0:#0.00}", _UIAlphaValue);
  
              var transparencySlider = _settingsWindow.GetChild("WindowContent").GetChild("UITransparencySliderHLG").GetChild("TransparencySlider");
  
              if(transparencySlider)
              {
                  var sliderControl = transparencySlider.GetComponent<Slider>();
                  sliderControl.minValue = UI_MIN_ALPHA;
                  sliderControl.maxValue = 1.0f;
                  sliderControl.value = _UIAlphaValue;
                  sliderControl.onValueChanged.AddListener(v => { alphaText.text = string.Format("{0:#0.00}", v);});
              }
  
              var scaleText = _settingsWindow.GetChild("WindowContent").GetChild("UIScaleSliderHLG").GetChild("ScaleValue").GetComponent<Text>();
              scaleText.text = string.Format("{0:#0.00}", _UIScaleValue);
  
              var scaleSlider = _settingsWindow.GetChild("WindowContent").GetChild("UIScaleSliderHLG").GetChild("ScaleSlider");
  
              if (scaleSlider)
              {
                  var sliderControl = scaleSlider.GetComponent<Slider>();
                  sliderControl.minValue = UI_MIN_SCALE;
                  sliderControl.maxValue = UI_MAX_SCALE;
                  sliderControl.value = _UIScaleValue;
                  sliderControl.onValueChanged.AddListener(v => { scaleText.text = string.Format("{0:#0.00}", v);});
              }
  
              var useECToggle = _settingsWindow.GetChild ("WindowContent").GetChild ("UseECHLG").GetChild ("UseECToggle").GetComponent<Toggle> ();
              useECToggle.isOn = UseElectricCharge;
              useECToggle.onValueChanged.AddListener (v => UseElectricCharge = v);
  
              var useECToggleTooltip = useECToggle.gameObject.AddComponent<BasicTooltip>();
              useECToggleTooltip.tooltipText = "Debug mode, no EC consumption.\nRequires scene change";
  
              var useBlizzyToggle = _settingsWindow.GetChild("WindowContent").GetChild("UseBlizzyHLG").GetChild("UseBlizzyToggle").GetComponent<Toggle>();
              useBlizzyToggle.isOn = useBlizzyToolbar;
              useBlizzyToggle.onValueChanged.AddListener(v => useBlizzyToolbar = v);
  
              var useBlizzyToggleTooltip = useBlizzyToggle.gameObject.AddComponent<BasicTooltip>();
              useBlizzyToggleTooltip.tooltipText = "Use blizzy's Toolbar.\nRequires scene change.";
  
              _settingsWindow.GetChild("WindowContent").GetChild("UseBlizzyHLG").SetActive(BlizzyToolbar.ToolbarManager.ToolbarAvailable);
  
              var footerButtons = _settingsWindow.GetChild("WindowFooter").GetChild("WindowFooterButtonsHLG");
  
              var cancelButton = footerButtons.GetChild("CancelButton").GetComponent<Button>();
              cancelButton.onClick.AddListener(() =>
                  {
                      transparencySlider.GetComponent<Slider>().value = _UIAlphaValue;
                      alphaText.text = string.Format("{0:#0.00}", _UIAlphaValue);
  
                      scaleSlider.GetComponent<Slider>().value = _UIScaleValue;
                      scaleText.text = string.Format("{0:#0.00}", _UIScaleValue);
                  });
  
              var defaultButton = footerButtons.GetChild("DefaultButton").GetComponent<Button>();
              defaultButton.onClick.AddListener(() =>
                  {
                      _UIAlphaValue = 0.8f;
                      _UIScaleValue = 1.0f;
  
                      transparencySlider.GetComponent<Slider>().value = _UIAlphaValue;
                      alphaText.text = string.Format("{0:#0.00}", _UIAlphaValue);
  
                      scaleSlider.GetComponent<Slider>().value = _UIScaleValue;
                      scaleText.text = string.Format("{0:#0.00}", _UIScaleValue);
  
                      SetGlobalAlpha(_UIAlphaValue);
                      SetGlobalScale(_UIScaleValue);
                  });
  
              var applyButton = footerButtons.GetChild("ApplyButton").GetComponent<Button>();
              applyButton.onClick.AddListener(() => 
                  {
                      float newAlphaValue = (float) Math.Round(transparencySlider.GetComponent<Slider>().value, 2);
                      float newScaleValue = (float) Math.Round(scaleSlider.GetComponent<Slider>().value, 2);
  
                      SetGlobalAlpha(newAlphaValue);
                      SetGlobalScale(newScaleValue);
                  });
              _settingsWindow.SetActive(false);
          }
  
          private void SetGlobalAlpha(float newAlpha)
          {
              _UIAlphaValue = Mathf.Clamp(newAlpha, UI_MIN_ALPHA, 1.0f);
  
              if (_controlWindow)
              {
                  _controlWindow.GetComponent<CanvasGroup>().alpha = _UIAlphaValue;
              }
              if (_settingsWindow)
              {
                  _settingsWindow.GetComponent<CanvasGroup>().alpha = _UIAlphaValue;
  
                  var alphaText = _settingsWindow.GetChild("WindowContent").GetChild("UITransparencySliderHLG").GetChild("TransparencyValue").GetComponent<Text>();
                  alphaText.text = string.Format("{0:#0.##}", _UIAlphaValue);
              }
              if (_editorWindow)
              {
                  _editorWindow.GetComponent<CanvasGroup>().alpha = _UIAlphaValue;
              }
          }
  
          private void SetGlobalScale(float newScale)
          {
              newScale = Mathf.Clamp(newScale, UI_MIN_SCALE, UI_MAX_SCALE);
  
              if(_controlWindow)
              {
                  _controlWindow.transform.localScale = Vector3.one * newScale;
              }
              if(_editorWindow)
              {
                  _editorWindow.transform.localScale = Vector3.one * newScale;
              }
              if(_settingsWindow)
              {
                  _settingsWindow.transform.localScale = Vector3.one * newScale;
  
                  var scaleText = _settingsWindow.GetChild("WindowContent").GetChild("UIScaleSliderHLG").GetChild("ScaleValue").GetComponent<Text>();
                  scaleText.text =  string.Format("{0:#0.##}", newScale);
              }
  
              if(_presetsWindow)
              {
                  _presetsWindow.transform.localScale = Vector3.one * newScale;
              }
  
              _UIScaleValue = newScale;
          }
  
          public void ToggleSettingsWindow()
          {
              if (_settingsWindow == null || _settingsWindowFader == null)
                  InitSettingsWindow();
  
              if (_settingsWindow.activeSelf)
              {
                  //fade the window out and deactivate
                  _settingsWindowFader.FadeTo(0, UI_FADE_TIME, () => _settingsWindow.SetActive(false));
              }
              else
              {
                  //activate and fade the window in,
                  _settingsWindow.SetActive(true);
                  _settingsWindowFader.FadeTo(_UIAlphaValue, UI_FADE_TIME);
              }
          }
  
          private void InitFlightControlWindow(bool startSolid = true)
          {
              _controlWindow = GameObject.Instantiate(UIAssetsLoader.controlWindowPrefab);
              _controlWindow.transform.SetParent(UIMasterController.Instance.appCanvas.transform, false);
              _controlWindow.GetChild("WindowTitle").AddComponent<PanelDragger>();
              _controlWindowFader = _controlWindow.AddComponent<CanvasGroupFader>();
  
              //start invisible to be toggled later
              if(!startSolid)
                  _controlWindow.GetComponent<CanvasGroup>().alpha = 0f;
  
              if (_controlWindowPosition == Vector3.zero)
              {
                  //get the default position from the prefab
                  _controlWindowPosition = _controlWindow.transform.position;
              }
              else
              {
                  _controlWindow.transform.position = ClampWindowPosition(_controlWindowPosition);
              }
  
              var settingsButton = _controlWindow.GetChild("WindowTitle").GetChild("LeftWindowButton");
              if (settingsButton != null)
              {
                  settingsButton.GetComponent<Button>().onClick.AddListener(ToggleSettingsWindow);
                  var t = settingsButton.AddComponent<BasicTooltip>();
                  t.tooltipText = "Show/hide UI settings";
              }
  
              var closeButton = _controlWindow.GetChild("WindowTitle").GetChild("RightWindowButton");
              if (closeButton != null)
              {
                  closeButton.GetComponent<Button>().onClick.AddListener(HideIRWindow);
                  var t = closeButton.AddComponent<BasicTooltip>();
                  t.tooltipText = "Close window";
              }
  
              var flightWindowFooterButtons = _controlWindow.GetChild ("WindowFooter").GetChild ("FlightWindowFooterButtonsHLG");
              var openEditorButton = flightWindowFooterButtons.GetChild ("EditGroupsButton").GetComponent<Button> ();
              openEditorButton.onClick.AddListener (ToggleFlightEditor);
  
              var openEditorButtonTooltip = openEditorButton.gameObject.AddComponent<BasicTooltip>();
              openEditorButtonTooltip.tooltipText = "Switch to Editor Mode";
  
              var presetModeToggle = flightWindowFooterButtons.GetChild ("PresetModeButton").GetComponent<Toggle> ();
              presetModeToggle.isOn = guiFlightPresetModeOn;
              presetModeToggle.onValueChanged.AddListener (ToggleFlightPresetMode);
  
              var presetModeTooltip = presetModeToggle.gameObject.AddComponent<BasicTooltip>();
              presetModeTooltip.tooltipText = "Toggle Preset Mode";
  
              var stopAllButton = flightWindowFooterButtons.GetChild ("StopAllButton").GetComponent<Button> ();
              stopAllButton.onClick.AddListener (() => {
                  foreach(var pair in _servoGroupUIControls)
                  {
                      pair.Key.Stop();
                  }
                  guiRebuildPending = true;
                  //TODO: we need to reset oll Movement Toggles
              });
  
              var stopAllTooltip = stopAllButton.gameObject.AddComponent<BasicTooltip>();
              stopAllTooltip.tooltipText = "Panic! Stop all servos!";
  
              //toggle preset mode if needed
              ToggleFlightPresetMode (guiFlightPresetModeOn);
  
          }
  
          private void InitFlightGroupControls(GameObject newServoGroupLine, ServoController.ControlGroup g)
          {
              var hlg = newServoGroupLine.GetChild("ServoGroupControlsHLG");
              var servosVLG = newServoGroupLine.GetChild("ServoGroupServosVLG");
  
              hlg.GetChild("ServoGroupNameText").GetComponent<Text>().text = g.Name;
              
              var groupToggle = hlg.GetChild("ServoGroupExpandedStatusToggle").GetComponent<Toggle>();
              var groupLockToggleIcon = hlg.GetChild("ServoGroupExpandedStatusToggle").GetChild("Icon").GetComponent<RawImage>();
              groupToggle.onValueChanged.AddListener(v =>
              {
                  groupLockToggleIcon.texture = UIAssetsLoader.iconAssets.Find(i => i.name == (g.Expanded ? "expand" : "collapse"));
                  
                  g.Expanded = v;
                  servosVLG.SetActive(g.Expanded);
              });
  
              if(g.Expanded)
                  groupLockToggleIcon.texture = UIAssetsLoader.iconAssets.Find(i => i.name == "collapse");
              servosVLG.SetActive(g.Expanded);
  
              var groupExpandTooltip = groupToggle.gameObject.AddComponent<BasicTooltip>();
              groupExpandTooltip.tooltipText = "Show/hide group's servos";
              
              var groupSpeed = hlg.GetChild("ServoGroupSpeedMultiplier").GetComponent<InputField>();
              groupSpeed.text = g.Speed;
              groupSpeed.onEndEdit.AddListener(v => { g.Speed = v; });
  
              var groupSpeedTooltip = groupSpeed.gameObject.AddComponent<BasicTooltip>();
              groupSpeedTooltip.tooltipText = "Speed Multiplier";
  
              var groupMoveLeftToggle = hlg.GetChild("ServoGroupMoveLeftToggleButton").GetComponent<Toggle>();
              groupMoveLeftToggle.isOn = g.MovingNegative;
              groupMoveLeftToggle.onValueChanged.AddListener(v =>
                  {
                      g.Stop ();
                      if (v) {
                          hlg.GetChild ("ServoGroupMoveRightToggleButton").GetComponent<Toggle> ().isOn = false;
                          g.MoveLeft ();
                          g.MovingNegative = true;
                          g.MovingPositive = false;
                      }
                  });
              var groupMoveLeftToggleTooltip = groupMoveLeftToggle.gameObject.AddComponent<BasicTooltip>();
              groupMoveLeftToggleTooltip.tooltipText = "Toggle negative movement";
  
              var groupMoveLeftButton = hlg.GetChild("ServoGroupMoveLeftButton");
              var groupMoveLeftHoldButton = groupMoveLeftButton.AddComponent<HoldButton>();
              groupMoveLeftHoldButton.callbackOnDown = g.MoveLeft;
              groupMoveLeftHoldButton.callbackOnUp = g.Stop;
  
              var groupMoveLeftTooltip = groupMoveLeftButton.AddComponent<BasicTooltip>();
              groupMoveLeftTooltip.tooltipText = "Hold to move negative";
              
              var groupMoveCenterButton = hlg.GetChild("ServoGroupMoveCenterButton");
              var groupMoveCenterHoldButton = groupMoveCenterButton.AddComponent<HoldButton>();
              groupMoveCenterHoldButton.callbackOnDown = g.MoveCenter;
              groupMoveCenterHoldButton.callbackOnUp = g.Stop;
  
              var groupMoveCenterTooltip = groupMoveCenterButton.AddComponent<BasicTooltip>();
              groupMoveCenterTooltip.tooltipText = "Hold to move \nto default position";
  
              var groupMoveRightButton = hlg.GetChild("ServoGroupMoveRightButton");
              var groupMoveRightHoldButton = groupMoveRightButton.AddComponent<HoldButton>();
              groupMoveRightHoldButton.callbackOnDown = g.MoveRight;
              groupMoveRightHoldButton.callbackOnUp = g.Stop;
  
              var groupMoveRightTooltip = groupMoveRightButton.AddComponent<BasicTooltip>();
              groupMoveRightTooltip.tooltipText = "Hold to move positive";
  
              var groupMoveRightToggle = hlg.GetChild("ServoGroupMoveRightToggleButton").GetComponent<Toggle>();
              groupMoveRightToggle.isOn = g.MovingPositive;
              groupMoveRightToggle.onValueChanged.AddListener(v =>
                  {
                      g.Stop();
                      if (v)
                      {
                          hlg.GetChild ("ServoGroupMoveLeftToggleButton").GetComponent<Toggle> ().isOn = false;
                          g.MoveRight();
                          g.MovingNegative = false;
                          g.MovingPositive = true;
                      }
                  });
  
              var groupMoveRightToggleTooltip = groupMoveRightToggle.gameObject.AddComponent<BasicTooltip>();
              groupMoveRightToggleTooltip.tooltipText = "Toggle positive movement";
  
              var groupMovePrevPresetButton = hlg.GetChild ("ServoGroupMovePrevPresetButton").GetComponent<Button>();
              groupMovePrevPresetButton.onClick.AddListener (g.MovePrevPreset);
  
              var groupMovePrevPresetTooltip = groupMovePrevPresetButton.gameObject.AddComponent<BasicTooltip>();
              groupMovePrevPresetTooltip.tooltipText = "Move to previous preset";
  
              var groupRevertButton = hlg.GetChild ("ServoGroupRevertButton").GetComponent<Button> ();
              groupRevertButton.onClick.AddListener (g.MoveCenter);
  
              var groupRevertTooltip = groupRevertButton.gameObject.AddComponent<BasicTooltip>();
              groupRevertTooltip.tooltipText = "Move to default position";
  
              var groupMoveNextPresetButton = hlg.GetChild ("ServoGroupMoveNextPresetButton").GetComponent<Button>();
              groupMoveNextPresetButton.onClick.AddListener (g.MoveNextPreset);
  
              var groupMoveNextPresetTooltip = groupMoveNextPresetButton.gameObject.AddComponent<BasicTooltip>();
              groupMoveNextPresetTooltip.tooltipText = "Move to next preset";
  
              //now list servos
              for (int j = 0; j < g.Servos.Count; j++)
              {
                  var s = g.Servos[j];
  
                  if (s.Mechanism.IsFreeMoving)
                      continue;
  
                  var newServoLine = GameObject.Instantiate(UIAssetsLoader.controlWindowServoLinePrefab);
                  newServoLine.transform.SetParent(servosVLG.transform, false);
  
                  InitFlightServoControls(newServoLine, s);
  
                  _servoUIControls.Add(s, newServoLine);
              }
          }
  
          private void InitFlightServoControls(GameObject newServoLine, IServo s)
          {
              var servoStatusLight = newServoLine.GetChild("ServoStatusRawImage").GetComponent<RawImage>();
              if (s.Mechanism.IsLocked)
              {
                  var redDot = UIAssetsLoader.iconAssets.Find(i => i.name == "IRWindowIndicator_Locked");
                  if (redDot != null)
                      servoStatusLight.texture = redDot;
              }
  
              var servoName = newServoLine.GetChild("ServoNameText").GetComponent<Text>();
              servoName.text = s.Name;
              var highlighter = servoName.gameObject.AddComponent<ServoHighlighter>();
              highlighter.servo = s;
  
              var servoPosition = newServoLine.GetChild("ServoPositionText").GetComponent<Text>();
              servoPosition.text = string.Format("{0:#0.00}", s.Mechanism.Position);
  
              var servoLockToggle = newServoLine.GetChild("ServoLockToggleButton").GetComponent<Toggle>();
              servoLockToggle.isOn = s.Mechanism.IsLocked;
              servoLockToggle.onValueChanged.AddListener(v =>
              {
                  s.Mechanism.IsLocked = v;
                  servoLockToggle.isOn = v;
              });
  
              var servoLockToggleTooltip = servoLockToggle.gameObject.AddComponent<BasicTooltip>();
              servoLockToggleTooltip.tooltipText = "Lock/unlock the servo";
  
              var servoMoveLeftButton = newServoLine.GetChild("ServoMoveLeftButton");
              var servoMoveLeftHoldButton = servoMoveLeftButton.AddComponent<HoldButton>();
              servoMoveLeftHoldButton.callbackOnDown = s.Motor.MoveLeft;
              servoMoveLeftHoldButton.callbackOnUp = s.Motor.Stop;
  
              var servoMoveLeftTooltip = servoMoveLeftButton.AddComponent<BasicTooltip>();
              servoMoveLeftTooltip.tooltipText = "Hold to move negative";
  
              var servoMoveCenterButton = newServoLine.GetChild("ServoMoveCenterButton");
              var servoMoveCenterHoldButton = servoMoveCenterButton.AddComponent<HoldButton>();
              servoMoveCenterHoldButton.callbackOnDown = s.Motor.MoveCenter;
              servoMoveCenterHoldButton.callbackOnUp = s.Motor.Stop;
  
              var servoMoveCenterTooltip = servoMoveCenterButton.AddComponent<BasicTooltip>();
              servoMoveCenterTooltip.tooltipText = "Hold to move\n to default position";
  
              var servoMoveRightButton = newServoLine.GetChild("ServoMoveRightButton");
              var servoMoveRightHoldButton = servoMoveRightButton.AddComponent<HoldButton>();
              servoMoveRightHoldButton.callbackOnDown = s.Motor.MoveRight;
              servoMoveRightHoldButton.callbackOnUp = s.Motor.Stop;
  
              var servoMoveRightTooltip = servoMoveRightButton.AddComponent<BasicTooltip>();
              servoMoveRightTooltip.tooltipText = "Hold to move negative";
  
              var servoInvertAxisToggle = newServoLine.GetChild("ServoInvertAxisToggleButton").GetComponent<Toggle>();
              servoInvertAxisToggle.isOn = s.Motor.IsAxisInverted;
              servoInvertAxisToggle.onValueChanged.AddListener(v =>
              {
                  s.Motor.IsAxisInverted = v;
                  servoInvertAxisToggle.isOn = v;
              });
  
              var servoInvertAxisToggleTooltip = servoInvertAxisToggle.gameObject.AddComponent<BasicTooltip>();
              servoInvertAxisToggleTooltip.tooltipText = "Invert/uninvert servo axis";
  
              var servoPrevPresetButton = newServoLine.GetChild ("ServoMovePrevPresetButton").GetComponent<Button> ();
              servoPrevPresetButton.onClick.AddListener (s.Preset.MovePrev);
  
              var servoPrevPresetTooltip = servoPrevPresetButton.gameObject.AddComponent<BasicTooltip>();
              servoPrevPresetTooltip.tooltipText = "Move to previous preset";
  
              var servoOpenPresetsToggle = newServoLine.GetChild ("ServoOpenPresetsToggle").GetComponent<Toggle> ();
              servoOpenPresetsToggle.onValueChanged.AddListener (v => TogglePresetEditWindow (s, v, servoOpenPresetsToggle.gameObject));
  
              var servoOpenPresetsToggleTooltip = servoOpenPresetsToggle.gameObject.AddComponent<BasicTooltip>();
              servoOpenPresetsToggleTooltip.tooltipText = "Open/close presets";
  
              var servoNextPresetButton = newServoLine.GetChild ("ServoMoveNextPresetButton").GetComponent<Button> ();
              servoNextPresetButton.onClick.AddListener (s.Preset.MoveNext);
  
              var servoNextPresetTooltip = servoNextPresetButton.gameObject.AddComponent<BasicTooltip>();
              servoNextPresetTooltip.tooltipText = "Move to next preset";
          }
  
          private void SetGroupPresetControlsVisibility(GameObject groupUIControls, bool value)
          {
              groupUIControls.GetChild("ServoGroupMoveLeftButton").SetActive(!value);
              groupUIControls.GetChild("ServoGroupMoveCenterButton").SetActive(!value);
              groupUIControls.GetChild("ServoGroupMoveRightButton").SetActive(!value);
  
              groupUIControls.GetChild("ServoGroupMovePrevPresetButton").SetActive(value);
              groupUIControls.GetChild("ServoGroupRevertButton").SetActive(value);
              groupUIControls.GetChild("ServoGroupMoveNextPresetButton").SetActive(value);
          }
  
          private void SetServoPresetControlsVisibility(GameObject servoUIControls, bool value)
          {
              servoUIControls.GetChild("ServoMoveLeftButton").SetActive(!value);
              servoUIControls.GetChild("ServoMoveCenterButton").SetActive(!value);
              servoUIControls.GetChild("ServoMoveRightButton").SetActive(!value);
  
              servoUIControls.GetChild("ServoMovePrevPresetButton").SetActive(value);
              servoUIControls.GetChild("ServoOpenPresetsToggle").SetActive(value);
              servoUIControls.GetChild("ServoMoveNextPresetButton").SetActive(value);
          }
  
          private void ToggleFlightPresetMode(bool value)
          {
              if (_controlWindow == null || _servoUIControls == null || _servoGroupUIControls == null)
                  return;
  
              guiFlightPresetModeOn = value;
  
              //we need to turn off preset buttons and turn on normal buttons
              foreach (var groupPair in _servoGroupUIControls)
              {
                  SetGroupPresetControlsVisibility(groupPair.Value, value);
              }
              foreach (var servoPair in _servoUIControls)
              {
                  SetServoPresetControlsVisibility(servoPair.Value, value);
              }
          }
  
          public void PresetInputOnEndEdit(string tmp, int i, GameObject buttonRef = null)
          {
              if (presetWindowServo == null)
                  return;
  
              float tmpValue = 0f;
  
gt:             if (float.TryParse(tmp, out tmpValue))