/// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // Warning that this component is OBSOLETE
            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "This component is OBSOLETE and will be removed " +
                              "in the future. Remove this component from your canvas and replace it by picking the new component " +
                              "from the ribbon.");

            // Input variables
            AbsoluteJointMovement absolutJointMovement = null;

            // Catch the input data
            if (!DA.GetData(0, ref absolutJointMovement))
            {
                return;
            }

            // Check if the object is valid
            if (!absolutJointMovement.IsValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "The Absolute Joint Movement is not valid");
            }

            // Output
            DA.SetData(0, absolutJointMovement.Name);
            DA.SetDataList(1, absolutJointMovement.InternalAxisValues);
            DA.SetDataList(2, absolutJointMovement.ExternalAxisValues);
            DA.SetData(3, absolutJointMovement.SpeedData);
            DA.SetData(4, absolutJointMovement.MovementType);
            DA.SetData(5, absolutJointMovement.ZoneData);
            DA.SetData(6, absolutJointMovement.RobotTool);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // Warning that this component is OBSOLETE
            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "This component is OBSOLETE and will be removed in the future. Instead, " +
                              "combine Joint Targets with Movements.");

            // Input variables
            List <string>            names = new List <string>();
            GH_Structure <GH_Number> internalAxisValuesTree = new GH_Structure <GH_Number>();
            GH_Structure <GH_Number> externalAxisValuesTree = new GH_Structure <GH_Number>();
            List <SpeedData>         speedDatas             = new List <SpeedData>();
            List <ZoneData>          zoneDatas  = new List <ZoneData>();
            List <RobotTool>         robotTools = new List <RobotTool>();

            // Create an empty Robot Tool
            RobotTool emptyRobotTool = new RobotTool();

            emptyRobotTool.Clear();

            // Catch the input data from the fixed parameters
            if (!DA.GetDataList(0, names))
            {
                return;
            }
            if (!DA.GetDataTree(1, out internalAxisValuesTree))
            {
                return;
            }
            if (!DA.GetDataTree(2, out externalAxisValuesTree))
            {
                return;
            }
            if (!DA.GetDataList(3, speedDatas))
            {
                return;
            }
            if (!DA.GetDataList(4, zoneDatas))
            {
                zoneDatas = new List <ZoneData>()
                {
                    new ZoneData(0)
                };
            }

            // Catch the input data from the variable parameteres
            if (Params.Input.Any(x => x.Name == variableInputParameters[0].Name))
            {
                if (!DA.GetDataList(variableInputParameters[0].Name, robotTools))
                {
                    robotTools = new List <RobotTool>()
                    {
                        new RobotTool(emptyRobotTool)
                    };
                }
            }

            // Make sure variable input parameters have a default value
            if (robotTools.Count == 0)
            {
                robotTools.Add(new RobotTool(emptyRobotTool)); // Empty Robot Tool
            }

            // Get longest Input List
            int[] sizeValues = new int[6];
            sizeValues[0] = names.Count;
            sizeValues[1] = internalAxisValuesTree.PathCount;
            sizeValues[2] = externalAxisValuesTree.PathCount;
            sizeValues[3] = speedDatas.Count;
            sizeValues[4] = zoneDatas.Count;
            sizeValues[5] = robotTools.Count;

            int biggestSize = HelperMethods.GetBiggestValue(sizeValues);

            // Keeps track of used indicies
            int namesCounter         = -1;
            int internalValueCounter = -1;
            int externalValueCounter = -1;
            int speedDataCounter     = -1;
            int precisionCounter     = -1;
            int robotToolCounter     = -1;

            // Clear list
            _jointMovements.Clear();

            // Creates movements
            for (int i = 0; i < biggestSize; i++)
            {
                string        name;
                List <double> internalAxisValues = new List <double>();
                List <double> externalAxisValues = new List <double>();

                SpeedData speedData;
                ZoneData  zoneData;
                RobotTool robotTool;

                // Target counter
                if (i < sizeValues[0])
                {
                    name = names[i];
                    namesCounter++;
                }
                else
                {
                    name = names[namesCounter] + "_" + (i - namesCounter);
                }

                // internal axis values counter
                if (i < sizeValues[1])
                {
                    internalAxisValues = internalAxisValuesTree[i].ConvertAll(x => (double)x.Value);
                    internalValueCounter++;
                }
                else
                {
                    internalAxisValues = internalAxisValuesTree[internalValueCounter].ConvertAll(x => (double)x.Value);
                }

                // External axis values counter
                if (sizeValues[2] == 0) // In case no external axis values are defined.
                {
                    externalAxisValues = new List <double>()
                    {
                    };
                }

                else
                {
                    if (i < sizeValues[2])
                    {
                        externalAxisValues = externalAxisValuesTree[i].ConvertAll(x => (double)x.Value);
                        externalValueCounter++;
                    }
                    else
                    {
                        externalAxisValues = externalAxisValuesTree[externalValueCounter].ConvertAll(x => (double)x.Value);
                    }
                }

                // SpeedData counter
                if (i < sizeValues[3])
                {
                    speedData = speedDatas[i];
                    speedDataCounter++;
                }
                else
                {
                    speedData = speedDatas[speedDataCounter];
                }

                // Precision counter
                if (i < sizeValues[4])
                {
                    zoneData = zoneDatas[i];
                    precisionCounter++;
                }
                else
                {
                    zoneData = zoneDatas[precisionCounter];
                }

                // Robot tool counter
                if (i < sizeValues[5])
                {
                    robotTool = robotTools[i];
                    robotToolCounter++;
                }
                else
                {
                    robotTool = robotTools[robotToolCounter];
                }

                // JointMovement constructor
                AbsoluteJointMovement jointMovement = new AbsoluteJointMovement(name, internalAxisValues, externalAxisValues, speedData, zoneData, robotTool);
                _jointMovements.Add(jointMovement);
            }

            // Check if an exact predefined zonedata value is used
            for (int i = 0; i < zoneDatas.Count; i++)
            {
                if (zoneDatas[i].ExactPredefinedValue == false & zoneDatas[i].PreDefinied == true)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Predefined zonedata value <" + i + "> is invalid. " +
                                      "The nearest valid predefined speeddata value is used. Valid predefined zonedata values are -1, " +
                                      "0, 1, 5, 10, 15, 20, 30, 40, 50, 60, 80, 100, 150 or 200. " +
                                      "A value of -1 will be interpreted as fine movement in RAPID Code.");
                    break;
                }
            }

            // Check if an exact predefined speeddata value is used
            for (int i = 0; i < speedDatas.Count; i++)
            {
                if (speedDatas[i].ExactPredefinedValue == false & speedDatas[i].PreDefinied == true)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Predefined speeddata value <" + i + "> is invalid. " +
                                      "The nearest valid predefined speeddata value is used. Valid predefined speeddata values are 5, 10, " +
                                      "20, 30, 40, 50, 60, 80, 100, 150, 200, 300, 400, 500, 600, 800, 1000, 1500, 2000, 2500, 3000, 4000, " +
                                      "5000, 6000 and 7000.");
                    break;
                }
            }

            // Output
            DA.SetDataList(0, _jointMovements);

            #region Object manager
            // Gets ObjectManager of this document
            _objectManager = DocumentManager.GetDocumentObjectManager(this.OnPingDocument());

            // Clears targetNames
            for (int i = 0; i < _targetNames.Count; i++)
            {
                _objectManager.TargetNames.Remove(_targetNames[i]);
            }
            _targetNames.Clear();

            // Removes lastName from targetNameList
            if (_objectManager.TargetNames.Contains(_lastName))
            {
                _objectManager.TargetNames.Remove(_lastName);
            }

            // Adds Component to JointTargetsByGuid Dictionary
            if (!_objectManager.OldJointTargetsByGuid2.ContainsKey(this.InstanceGuid))
            {
                _objectManager.OldJointTargetsByGuid2.Add(this.InstanceGuid, this);
            }

            // Checks if target name is already in use and counts duplicates
            #region Check name in object manager
            _namesUnique = true;
            for (int i = 0; i < names.Count; i++)
            {
                if (_objectManager.TargetNames.Contains(names[i]))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Target Name already in use.");
                    _namesUnique = false;
                    _lastName    = "";
                    break;
                }
                else
                {
                    // Adds Target Name to list
                    _targetNames.Add(names[i]);
                    _objectManager.TargetNames.Add(names[i]);

                    // Run SolveInstance on other Targets with no unique Name to check if their name is now available
                    _objectManager.UpdateTargets();

                    _lastName = names[i];
                }

                // Checks if variable name exceeds max character limit for RAPID Code
                if (HelperMethods.VariableExeedsCharacterLimit32(names[i]))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Target Name exceeds character limit of 32 characters.");
                    break;
                }

                // Checks if variable name starts with a number
                if (HelperMethods.VariableStartsWithNumber(names[i]))
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Target Name starts with a number which is not allowed in RAPID Code.");
                    break;
                }
            }
            #endregion

            // Recognizes if Component is Deleted and removes it from Object Managers target and name list
            GH_Document doc = this.OnPingDocument();
            if (doc != null)
            {
                doc.ObjectsDeleted += DocumentObjectsDeleted;
            }
            #endregion
        }