using System;
using System.Collections;
using System.Collections.Generic;

//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;

//namespace McGuffinsOfflineNetworkWorkshop {
    public class MNode {
        // Data members that you want serialized into XML need to be public.
        // Data members that should NOT be serialized need to be private or marked with [System.Xml.Serialization.XmlIgnoreAttribute]

        [System.Xml.Serialization.XmlIgnoreAttribute]
        private MNetwork net;

        public string label_string = "";
        // label strings are always 2 characters long, and the following fields are indices into a custom font
        public int label_char1 = 0;
        public int label_char2 = 0;

        public float x_2D, y_2D; // source coordinate system; saved to file
        public float labelSize_x_2D, labelSize_y_2D;
        public float x_3D, y_3D, z_3D; // source coordinate system; saved to file

        [System.Xml.Serialization.XmlIgnoreAttribute]
        public float x, y, z; // only used at runtime, to perform 2D and 3D layout; source coordinate system; see MNetwork.restoreSaved*CoordinatesToTemporaryCoordinates()

        [System.Xml.Serialization.XmlIgnoreAttribute]
        public float x_2D_target, y_2D_target, z_2D_target, x_3D_target, y_3D_target, z_3D_target; // coordinates in the target space

        public List<int> indicesOfEdges = new List<int>(); // these are indices of edges in the network's list of edges

        // Used in the force-directed layout algorithms
        // to temporarily store components of pseudo "forces" acting on this node.
        // These components are later used to update the node's position.
        //
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public float forceX, forceY, forceZ;

        // We assume that each node is "owned" by only one network.
        // Within a network, each node has a corresponding index
        // that can be used to look up the node in an array (or vector or something similar)
        // of nodes that is maintained by the network.
        // The same index also corresponds to the node's row and column
        // in the network's adjacency matrix.
        // To make it easier to determine the index for a given node,
        // we have the following data member that can be used to cache the node's index.
        // If a few nodes get deleted or added to the network,
        // causing the index stored here to become invalid,
        // we can simply lazily update it whenever we find it to be incorrect.
        // (The updating happens in MNetwork.getIndexOfNode() )
        //
        [System.Xml.Serialization.XmlIgnoreAttribute]
        private int index = -1;

        // Used for Breadth-First Search
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public bool bfs_isDiscovered = false;
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public MNode bfs_predecessor;

        // Used for Dijkstra's algorithm
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public float dijk_min_distance;
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public MNode dijk_predecessor;
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public int dijk_state;

        // Used in visibility graph
        [System.Xml.Serialization.XmlIgnoreAttribute]
        public MNode visibility_originalNode;



        // a constructor that takes no parameters is necessary for XML serialization to work
        public MNode() {
        }
        public void setNetwork( MNetwork n ) {
            net = n;
        }

        public void setIndex(int i) {
            index = i;
        }

        // Note: the index returned here is not guaranteed to be correct.
        // Clients who want an index guaranteed to be correct
        // should call MNetwork.getIndexOfNode()
        public int getIndex() {
            return index;
        }

        public int degree() { return indicesOfEdges.Count; }
        public int getIndexOfIthNeighbor(int i /* >= 0 and < degree() */ ) {
            int indexOfThisNode = net.getIndexOfNode(this); // this is a guaranteed correct index
            return net.edges[indicesOfEdges[i]].getIndexOfOtherNode(indexOfThisNode);
        }
        public MNode getIthNeighbor( int i /* >= 0 and < degree() */) {
            MLogger.Assert(net!=null,"n8zxl2oafq");
            MLogger.Assert(net.nodes != null, "1qb9dysibs");
            MLogger.Assert( i >= 0, "fikzvni7le");
            MLogger.Assert(getIndexOfIthNeighbor(i) >= 0, "57zhogx6x9");
            MLogger.Assert(getIndexOfIthNeighbor(i) < net.nodes.Count , "tqujduyh9t");
            return net.nodes[getIndexOfIthNeighbor(i)];
        }

        public MVector3 getPosition() {
            return new MVector3(x, y, z);
        }
        public MVector2 getPosition_2D() {
            return new MVector2(x_2D, y_2D);
        }
        public MVector3 getPosition_target(bool is2D) {
            return is2D
                ? new MVector3( x_2D_target, y_2D_target, z_2D_target )
                : new MVector3( x_3D_target, y_3D_target, z_3D_target );
        }
        public MAlignedRect2 getRect2D() {
            float w = labelSize_x_2D;
            float h = labelSize_y_2D;
            return new MAlignedRect2( new MVector2(x_2D-w/2, y_2D-h/2), new MVector2(x_2D+w/2, y_2D+h/2) );
        }
    }
//}

