//This code layout aims to have the highest readability level possible. Dialogues are broken into tutorial stages and sections. Magic numbers correspond to the total sections listed above
        //in the StringConstants class.
        public void OnClickAction()
        {
            switch (this.currentTutorialStage)
            {
            default:
            case Parts.Error:
                this.currentTutorialStage = Parts.Invalid;
                Debug.LogError("Current tutorial state has hit error. It will be reset to Invalid state.");
                break;

            case Parts.Invalid:
                Debug.LogWarning("Current tutorial state has hit an invalid state. Please check.");
                break;

            case Parts.Introduction:
                this.dialogue = StringConstants.Values(this.currentTutorialStage, this.dialogueSectionCounter);
                if (this.dialogueSectionCounter >= StringConstants.INTRODUCTION_SIZE)
                {
                    this.ReturnToSections();
                    break;
                }
                GameObject img = null;
                //Image index 0 ~ 5: General Section
                //ImageManager.Obtain() takes in image index as parameter, to display which specific image to show.
                //Image index is determined at compile time, while placing images in the Unity editor.
                switch (this.dialogueSectionCounter)
                {
                case 1:
                    img = this.imageManager.Obtain(0);
                    img.SetActive(true);
                    break;

                case 2:
                    img = this.imageManager.Obtain(0);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(1);
                    img.SetActive(true);
                    break;

                case 3:
                    img = this.imageManager.Obtain(1);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(2);
                    img.SetActive(true);
                    break;

                case 4:
                    img = this.imageManager.Obtain(2);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(5);
                    img.SetActive(true);
                    break;

                case 5:
                    img = this.imageManager.Obtain(5);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(3);
                    img.SetActive(true);
                    break;

                case 6:
                    img = this.imageManager.Obtain(3);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(4);
                    img.SetActive(true);
                    break;

                case 7:
                    img = this.imageManager.Obtain(4);
                    img.SetActive(false);
                    break;

                default:
                    for (int i = 0; i < this.imageManager.images.Count; i++)
                    {
                        img = this.imageManager.Obtain(i);
                        img.SetActive(false);
                    }
                    break;
                }
                this.dialogueSectionCounter++;
                break;

            //Image index 6 ~ 12: Attributes Editor
            case Parts.Attributes_Editor:
                this.dialogue = StringConstants.Values(this.currentTutorialStage, this.dialogueSectionCounter);
                if (this.dialogueSectionCounter >= StringConstants.ATTRIBUTES_EDITOR_SIZE)
                {
                    this.ReturnToSections();
                    break;
                }
                switch (this.dialogueSectionCounter)
                {
                case 1:
                    img = this.imageManager.Obtain(6);
                    img.SetActive(true);
                    break;

                case 2:
                    img = this.imageManager.Obtain(6);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(7);
                    img.SetActive(true);
                    break;

                case 3:
                    img = this.imageManager.Obtain(8);
                    img.SetActive(true);
                    break;

                case 4:
                    img = this.imageManager.Obtain(7);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(8);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(9);
                    img.SetActive(true);
                    break;

                case 5:
                    img = this.imageManager.Obtain(9);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(10);
                    img.SetActive(true);
                    break;

                case 6:
                    img = this.imageManager.Obtain(10);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(11);
                    img.SetActive(true);
                    break;

                case 7:
                    img = this.imageManager.Obtain(11);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(12);
                    img.SetActive(true);
                    break;

                case 10:
                    img = this.imageManager.Obtain(12);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(13);
                    img.SetActive(true);
                    break;

                case 11:
                    img = this.imageManager.Obtain(13);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(14);
                    img.SetActive(true);
                    break;

                case 12:
                    img = this.imageManager.Obtain(14);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(15);
                    img.SetActive(true);
                    break;

                case 13:
                    img = this.imageManager.Obtain(15);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(16);
                    img.SetActive(true);
                    break;

                case 14:
                    img = this.imageManager.Obtain(16);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(17);
                    img.SetActive(true);
                    break;

                case 15:
                    img = this.imageManager.Obtain(17);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(18);
                    img.SetActive(true);
                    break;

                case 18:
                    img = this.imageManager.Obtain(18);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(19);
                    img.SetActive(true);
                    break;

                case 19:
                    img = this.imageManager.Obtain(19);
                    img.SetActive(false);
                    break;

                default:
                    //for (int i = 0; i < this.imageManager.images.Count; i++) {
                    //	img = this.imageManager.Obtain(i);
                    //	img.SetActive(false);
                    //}
                    break;
                }
                this.dialogueSectionCounter++;
                break;

            case Parts.Camera_Controls:
                this.dialogue = StringConstants.Values(this.currentTutorialStage, this.dialogueSectionCounter);
                if (this.dialogueSectionCounter >= StringConstants.CAMERA_CONTROLS_SIZE)
                {
                    this.ReturnToSections();
                    break;
                }
                switch (this.dialogueSectionCounter)
                {
                case 1:
                    this.mainCameraPanning.enabled = true;
                    this.uiBorderPanel.gameObject.SetActive(true);
                    break;

                case 2:
                    this.uiBorderPanel.gameObject.SetActive(false);
                    break;

                case 3:
                    this.minimapCamera.enabled = true;
                    this.minimap.enabled       = true;
                    break;

                default:
                    for (int i = 0; i < this.imageManager.images.Count; i++)
                    {
                        img = this.imageManager.Obtain(i);
                        img.SetActive(false);
                    }
                    break;
                }
                this.dialogueSectionCounter++;
                break;

            case Parts.Unit_Controls:
                this.dialogue = StringConstants.Values(this.currentTutorialStage, this.dialogueSectionCounter);
                if (this.dialogueSectionCounter >= StringConstants.UNIT_CONTROLS_SIZE)
                {
                    //this.currentTutorialStage = Parts.Unit_Controls;
                    //this.dialogueSectionCounter = StringConstants.UNIT_CONTROLS_SIZE;
                    //this.isTutorialFinished = true;
                    //this.nextStepButton.interactable = false;
                    this.distanceUnitParent.gameObject.SetActive(false);
                    this.ReturnToSections();
                    break;
                }
                switch (this.dialogueSectionCounter)
                {
                case 0:
                    this.tutorialUnit.gameObject.SetActive(true);
                    this.minimap.enabled               = false;
                    this.minimapCamera.enabled         = false;
                    this.mainCamera.transform.position = this.cameraOrigin;
                    this.Invoke("DelayTurnOffCameraPanning", 0.1f);
                    break;

                case 3:
                    //Dragging selection box.
                    this.mainCursor.DragSelectionBox(this.mainCamera, this.GetNextPanning(), CursorButton.Left_Click, this, 3f, "DelayShowSelectionRing");
                    break;

                case 5:
                    //Splitting
                    GameObject clone = MonoBehaviour.Instantiate(this.tutorialUnit.gameObject) as GameObject;
                    clone.SetActive(true);
                    clone.transform.SetParent(this.tutorialUnitParent);
                    this.splitMergeManager.splitGroupList.Add(new Group(this.tutorialUnit.gameObject, clone));

                    //Stop selecting the unit.
                    this.Invoke("DelayHideSelectionRing", 0.1f);
                    break;

                case 8:
                    //Dragging selection box.
                    this.mainCursor.DragSelectionBox(this.mainCamera, this.GetNextPanning(), CursorButton.Left_Click, this, 3f, "DelayShowAllSelectionRings");
                    this.Invoke("DelayMergeUnits", 4f);
                    break;

                case 12:
                    //TODO(Thompson): Show what a non-positive upgrade is for unit customization, via animation.
                    if (this.tutorialUnitParent != null)
                    {
                        this.tutorialUnitParent.gameObject.SetActive(false);
                    }
                    if (this.nonPositiveUnitParent != null)
                    {
                        this.nonPositiveUnitParent.gameObject.SetActive(true);
                    }
                    break;

                case 14:
                    if (this.nonPositiveUnitParent != null)
                    {
                        this.nonPositiveUnitParent.gameObject.SetActive(false);
                    }
                    break;

                case 16:
                    //TODO(Thompson): Show how long the line of sight distance will be for LV1 unit and LV2 unit. Compare them via animation.
                    if (this.distanceUnitParent != null)
                    {
                        this.distanceUnitParent.gameObject.SetActive(true);
                    }
                    break;

                case 17:
                    if (this.distanceUnitParent != null)
                    {
                        this.distanceUnitParent.gameObject.SetActive(false);
                    }
                    img = this.imageManager.Obtain(20);
                    img.SetActive(true);
                    break;

                case 18:
                    img = this.imageManager.Obtain(20);
                    img.SetActive(false);
                    img = this.imageManager.Obtain(21);
                    img.SetActive(true);
                    break;

                case 19:
                    img = this.imageManager.Obtain(21);
                    img.SetActive(false);
                    break;

                default:
                    break;
                }
                this.dialogueSectionCounter++;
                break;
            }
            this.dialogueText.text    = "";
            this.stringLetterCounter  = 0;
            this.startTextRollingFlag = true;
        }
        public void Start()
        {
            TutorialAIManager.Instance = this;

            this.isInitialized = false;

            this.isTutorialFinished = false;
            this.delay                  = 0f;
            this.delayInterval          = 0f;
            this.dialogueSectionCounter = 0;
            this.currentTutorialStage   = Parts.Introduction;
            this.dialogue               = StringConstants.Values(this.currentTutorialStage, this.dialogueSectionCounter);
            this.dialogueSectionCounter++;
            this.stringLetterCounter  = 0;
            this.startTextRollingFlag = true;
            if (this.dialogueText != null)
            {
                this.dialogueText.text = "";
            }
            if (this.mainCamera == null)
            {
                Debug.LogError("Cannot obtain main camera. Please check.");
            }
            this.cameraOrigin = this.mainCamera.transform.position;

            this.mainCameraPanning = this.mainCamera.GetComponent <CameraPanning>();
            if (this.mainCameraPanning != null)
            {
                this.mainCameraPanning.enabled = false;
            }
            this.minimapCamera = this.minimap.GetComponent <Camera>();
            if (this.minimapCamera != null)
            {
                this.minimapCamera.enabled = false;
            }
            if (this.minimap == null)
            {
                Debug.LogError("Couldn't obtain minimap stuffs. Please check.");
            }
            if (this.nextStepButton == null)
            {
                Debug.LogError("The next button isn't set.");
            }
            if (this.dialogueText == null)
            {
                Debug.LogError("Dialogue text field is not bind to this variable.");
            }
            if (this.tutorialSections == null)
            {
                Debug.LogError("Tutorial sections are not set.");
            }
            if (this.dialogueBox == null)
            {
                Debug.LogError("Dialogue box not set.");
            }

            //Cursor setup
            GameObject obj = MonoBehaviour.Instantiate(this.cursorPrefab) as GameObject;

            obj.transform.SetParent(this.mainCanvas.transform);
            this.mainCursor = obj.GetComponent <Cursor>();
            if (this.mainCursor == null)
            {
                Debug.LogError("Cursor isn't obtained. Please check.");
            }

            InitializeCursorPanGroups();
            InitializeTutorial();
        }