/*
     * InitializeNodes() is a helper function for loading Story Dialog Editor data.
     *
     * Returns the mapping of input connection points and their associated output connection points
     */
    private static Dictionary <int, List <int> > InitializeNodes(EditorStoryNodeEntry storyEntry, Dictionary <int, ConnectionPoint> connectionPointMap)
    {
        // the map of input points and their associated output points
        Dictionary <int, List <int> > connectionMap = new Dictionary <int, List <int> >();

        // generate nodes and data from entries
        Node tempNode;

        foreach (EditorNodeEntry entry in storyEntry.nodes)
        {
            tempNode = NodeManager.AddNodeAt(new Vector2(entry.rect.x, entry.rect.y), entry.nodeType, markHistory: false, center: false);
            connectionPointMap[entry.inPoint.CPEID] = tempNode.inPoint;
            connectionMap[entry.inPoint.CPEID]      = entry.inPoint.linkedCPEIDs;

            // add flag data if set local/global
            if (entry.nodeType == NodeType.SetLocalFlag || entry.nodeType == NodeType.CheckLocalFlag)
            {
                tempNode.localFlagDropdown.selectedItem = mainEditor.localFlagsMenu.GetTextArea(entry.selectedFlag);
            }
            else if (entry.nodeType == NodeType.SetGlobalFlag || entry.nodeType == NodeType.CheckGlobalFlag)
            {
                tempNode.globalItemDropdown.selectedItem = entry.selectedFlag;
            }
            else if (entry.nodeType == NodeType.SetGlobalVariable || entry.nodeType == NodeType.CheckGlobalVariable)
            {
                tempNode.globalItemDropdown.selectedItem = entry.selectedFlag;
                tempNode.globalVariableField.text        = entry.globalVariableValue;
            }

            // map Node outpoint/splitter depending on NodeType
            if (entry.nodeType == NodeType.SetLocalFlag ||
                entry.nodeType == NodeType.SetGlobalFlag ||
                entry.nodeType == NodeType.SetGlobalVariable ||
                entry.nodeType == NodeType.Interrupt)
            {
                // add outpoint entry if available
                if (tempNode.outPoint != null && entry.outPoint != null)
                {
                    connectionPointMap[entry.outPoint.CPEID] = tempNode.outPoint;
                }
            }
            else if (entry.nodeType == NodeType.CheckLocalFlag ||
                     entry.nodeType == NodeType.CheckGlobalFlag ||
                     entry.nodeType == NodeType.CheckGlobalVariable)
            {
                // add splitter entries if available
                if (tempNode.splitter != null && entry.outPos != null && entry.outNeg != null)
                {
                    connectionPointMap[entry.outPos.CPEID] = tempNode.splitter.positiveOutpoint;
                    connectionPointMap[entry.outNeg.CPEID] = tempNode.splitter.negativeOutpoint;
                }
            }

            // record child container outpoints depending on NodeType and populate fields
            if (entry.nodeType == NodeType.Dialog || entry.nodeType == NodeType.Decision)
            {
                DBox child = tempNode.childContainer as DBox;
                SDEContainerEntry childEntry = entry.childContainer;

                while (childEntry != null)
                {
                    // set text and outpoint mapping for the child container
                    child.textArea.text = childEntry.text;
                    connectionPointMap[childEntry.outPoint.CPEID] = child.outPoint;

                    childEntry = childEntry.child;

                    // generate the child's child if there needs to be one
                    if (childEntry != null)
                    {
                        switch (entry.nodeType)
                        {
                        case NodeType.Dialog:
                            child.child = ScriptableObject.CreateInstance <DialogBox>();
                            ((DialogBox)child.child).Init(child, "");
                            break;

                        case NodeType.Decision:
                            child.child = ScriptableObject.CreateInstance <DecisionBox>();
                            ((DecisionBox)child.child).Init(child, "");
                            break;
                        }
                    }

                    child = child.child as DBox;
                }
            }
            else if (entry.nodeType == NodeType.Interrupt)
            {
                tempNode.SetBottomLevelInterrupt(entry.bottomLevel);

                DialogInterrupt   child;
                SDEContainerEntry childEntry = entry.childContainer;

                if (childEntry != null)
                {
                    // create the first child of the parent node
                    tempNode.childContainer = ScriptableObject.CreateInstance <DialogInterrupt>();
                    tempNode.childContainer.Init(tempNode);
                    ((DialogInterrupt)tempNode.childContainer).label.text = childEntry.text;

                    // record the connection point
                    connectionPointMap[childEntry.outPoint.CPEID] = tempNode.childContainer.outPoint;

                    child      = tempNode.childContainer as DialogInterrupt;
                    childEntry = childEntry.child;

                    while (childEntry != null)
                    {
                        // generate the child interrupt and populate it
                        child.child = ScriptableObject.CreateInstance <DialogInterrupt>();
                        ((DialogInterrupt)child.child).Init(child);
                        ((DialogInterrupt)child.child).label.text = childEntry.text;

                        // record the connection point
                        connectionPointMap[childEntry.outPoint.CPEID] = child.child.outPoint;

                        child      = child.child as DialogInterrupt;
                        childEntry = childEntry.child;
                    }
                }
            }
        }

        return(connectionMap);
    }
    // goes through everything and assigns CPEIDs to every ConnectionPointEntry and populates container data
    public static List <EditorNodeEntry> PrepassNodeEntries(List <Node> nodes, Dictionary <EditorNodeEntry, Node> nodeMap, Dictionary <ConnectionPoint, int> connectionPointMap)
    {
        List <EditorNodeEntry> entries = new List <EditorNodeEntry>();
        EditorNodeEntry        tempNode;

        for (int i = 0; i < nodes.Count; i++)
        {
            tempNode          = new EditorNodeEntry();
            nodeMap[tempNode] = nodes[i];

            tempNode.inPoint       = new InPointEntry();
            tempNode.inPoint.CPEID = GenerateCPEID();
            connectionPointMap[nodes[i].inPoint] = tempNode.inPoint.CPEID;

            // assign CPEID to outpoints and splitter points based on NodeType
            NodeType type = nodes[i].nodeType;
            if ((type == NodeType.Interrupt ||
                 type == NodeType.SetGlobalFlag ||
                 type == NodeType.SetLocalFlag ||
                 type == NodeType.SetGlobalVariable) &&
                nodes[i].outPoint != null)
            {
                tempNode.outPoint       = new ConnectionPointEntry();
                tempNode.outPoint.CPEID = GenerateCPEID();
                connectionPointMap[nodes[i].outPoint] = tempNode.outPoint.CPEID;
            }

            if ((type == NodeType.CheckGlobalFlag ||
                 type == NodeType.CheckLocalFlag ||
                 type == NodeType.CheckGlobalVariable) &&
                nodes[i].splitter != null)
            {
                tempNode.outPos       = new ConnectionPointEntry();
                tempNode.outNeg       = new ConnectionPointEntry();
                tempNode.outPos.CPEID = GenerateCPEID();
                tempNode.outNeg.CPEID = GenerateCPEID();
                connectionPointMap[nodes[i].splitter.positiveOutpoint] = tempNode.outPos.CPEID;
                connectionPointMap[nodes[i].splitter.negativeOutpoint] = tempNode.outNeg.CPEID;
            }

            // check if it has child elements based on NodeType
            if ((type == NodeType.Interrupt ||
                 type == NodeType.Dialog ||
                 type == NodeType.Decision) &&
                nodes[i].childContainer != null)
            {
                // traverse through the child components and populate the CPEIDs
                SDEContainer      container     = nodes[i].childContainer;
                SDEContainerEntry tempContainer = new SDEContainerEntry();
                tempNode.childContainer = tempContainer;
                while (container != null)
                {
                    tempContainer.outPoint                 = new ConnectionPointEntry();
                    tempContainer.outPoint.CPEID           = GenerateCPEID();
                    connectionPointMap[container.outPoint] = tempContainer.outPoint.CPEID;

                    // get container data
                    switch (container.containerType)
                    {
                    case SDEContainerType.DecisionBox:
                        tempContainer.text = ((DecisionBox)container).textArea.text;
                        break;

                    case SDEContainerType.DialogBox:
                        tempContainer.text = ((DialogBox)container).textArea.text;
                        break;

                    case SDEContainerType.DialogInterrupt:
                        tempContainer.text = ((DialogInterrupt)container).label.text;
                        break;

                    default:
                        throw new UnityException("Malformed SDEContainerType on Save!");
                    }

                    container = container.child;

                    if (container != null)
                    {
                        tempContainer.child = new SDEContainerEntry();
                        tempContainer       = tempContainer.child;
                    }
                }
            }

            entries.Add(tempNode);
        }

        // reset the CPEID counter after assignments are done
        CPEIDCounter = 0;
        return(entries);
    }