private void MoveElectron()
    {
        foreach (InputComponent ic in input)
        {
            int  i = input.IndexOf(ic);
            bool _tempVal;
            ic.Compute(_logicVals [i], out _tempVal);
            _logicVals [i]  = _tempVal;
            electronPos [i] = ic.MoveElectron();
            Debug.Log("Electron moved through INPUT " + electronPos [i] + " with value =" + _logicVals[i]);
            GridHandler.SpotType type = _grid.GetComponentType(electronPos [i].x, electronPos [i].y, electronPos [i].z);
            switch (type)
            {
            case GridHandler.SpotType.EMPTY:
                Debug.LogError("Disconnected input wire at " + electronPos [i]);
                break;

            case GridHandler.SpotType.INPUT_A:
                Debug.LogError("Input wires cannot be connected to each other");
                break;

            case GridHandler.SpotType.INPUT_B:
                Debug.LogError("Input wires cannot be connected to each other");
                break;

            case GridHandler.SpotType.INPUT_C:
                Debug.LogError("Input wires cannot be connected to each other");
                break;

            case GridHandler.SpotType.NOT:
                PerformNotOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.WIRE:
                PerformWireOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.OUTPUT:
                FinalOutput(electronPos [i], i);
                break;

            case GridHandler.SpotType.OR_LEFT:
                PerformWireOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.OR_RIGHT:
                PerformWireOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.OR_CENTRE:
                PerformOrOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.SPLITTER:
                PerformSplitOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.AND_LEFT:
                PerformWireOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.AND_RIGHT:
                PerformWireOperation(electronPos [i], i);
                break;

            case GridHandler.SpotType.AND_CENTRE:
                PerformAndOperation(electronPos [i], i);
                break;
            }
        }
    }
    private void PerformAndOperation(IVector3 pos, int index)
    {
        foreach (ANDComponent ac in and)
        {
            if (ac.Position == pos)
            {
                if (ac.Input.Count == 1)
                {
                    ac.Input.Add(_logicVals [index]);
                    bool _tempVal;
                    ac.Compute(out _tempVal);
                    _logicVals [index] = _tempVal;
                    //_logicVals.RemoveAt (index);
                    electronPos [index] = ac.MoveElectron();
                    Debug.Log("Electron moved through OR " + electronPos [index] + " with value =" + _tempVal);
                    GridHandler.SpotType type = _grid.GetComponentType(electronPos [index].x, electronPos [index].y, electronPos [index].z);
                    switch (type)
                    {
                    case GridHandler.SpotType.EMPTY:
                        Debug.LogError("Disconnected input wire at " + electronPos [index]);
                        break;

                    case GridHandler.SpotType.INPUT_A:
                        Debug.LogError("Input wires cannot be connected to each other");
                        break;

                    case GridHandler.SpotType.INPUT_B:
                        Debug.LogError("Input wires cannot be connected to each other");
                        break;

                    case GridHandler.SpotType.INPUT_C:
                        Debug.LogError("Input wires cannot be connected to each other");
                        break;

                    case GridHandler.SpotType.NOT:
                        PerformNotOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.WIRE:
                        PerformWireOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.OUTPUT:
                        FinalOutput(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.OR_LEFT:
                        PerformWireOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.OR_RIGHT:
                        PerformWireOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.OR_CENTRE:
                        PerformOrOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.AND_CENTRE:
                        PerformAndOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.AND_LEFT:
                        PerformWireOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.AND_RIGHT:
                        PerformWireOperation(electronPos [index], index);
                        break;

                    case GridHandler.SpotType.SPLITTER:
                        PerformSplitOperation(electronPos [index], index);
                        break;
                    }
                }
                else
                {
                    ac.Input.Add(_logicVals [index]);
                }
            }
        }
    }
    private void PerformSplitOperation(IVector3 pos, int index)
    {
        int newIndex;

        foreach (SplitterComponent sc in splitter)
        {
            if (sc.Position == pos)
            {
                bool newValAdded = _logicVals [index];
                _logicVals.Add(newValAdded);
                newIndex = _logicVals.Count - 1;
                bool _tempVal1, _tempVal2;
                sc.Compute(_logicVals [index], out _tempVal1);
                sc.Compute(_logicVals [newIndex], out _tempVal2);
                _logicVals [index]    = _tempVal1;
                _logicVals [newIndex] = _tempVal2;

                IVector3 newPos = sc.MoveSecElectron();
                electronPos.Add(newPos);
                electronPos [index] = sc.MoveElectron();
                Debug.Log("Electron moved through SPLITTER " + electronPos [index] + " with value =" + _logicVals[index] + " and " + electronPos [newIndex] + " with value =" + _logicVals[newIndex]);
                GridHandler.SpotType type1 = _grid.GetComponentType(electronPos [index].x, electronPos [index].y, electronPos [index].z);
                GridHandler.SpotType type2 = _grid.GetComponentType(electronPos [newIndex].x, electronPos [newIndex].y, electronPos [newIndex].z);
                switch (type1)
                {
                case GridHandler.SpotType.EMPTY:
                    Debug.LogError("Disconnected wire at " + electronPos [index]);
                    break;

                case GridHandler.SpotType.INPUT_A:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.INPUT_B:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.INPUT_C:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.NOT:
                    PerformNotOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.WIRE:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OUTPUT:
                    FinalOutput(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OR_LEFT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OR_RIGHT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OR_CENTRE:
                    PerformOrOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.SPLITTER:
                    PerformSplitOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_CENTRE:
                    PerformAndOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_LEFT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_RIGHT:
                    PerformWireOperation(electronPos [index], index);
                    break;
                }
                switch (type2)
                {
                case GridHandler.SpotType.EMPTY:
                    Debug.LogError("Disconnected wire at " + electronPos [newIndex]);
                    break;

                case GridHandler.SpotType.INPUT_A:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.INPUT_B:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.INPUT_C:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.NOT:
                    PerformNotOperation(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.WIRE:
                    PerformWireOperation(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.OUTPUT:
                    FinalOutput(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.OR_LEFT:
                    PerformWireOperation(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.OR_RIGHT:
                    PerformWireOperation(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.OR_CENTRE:
                    PerformOrOperation(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.SPLITTER:
                    PerformSplitOperation(electronPos [newIndex], newIndex);
                    break;

                case GridHandler.SpotType.AND_CENTRE:
                    PerformAndOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_LEFT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_RIGHT:
                    PerformWireOperation(electronPos [index], index);
                    break;
                }
            }
        }
    }
    private void FindAllComponents()
    {
        input       = new List <InputComponent> ();
        wires       = new List <WireComponent> ();
        not         = new List <NOTComponent> ();
        or          = new List <ORComponent> ();
        splitter    = new List <SplitterComponent> ();
        and         = new List <ANDComponent> ();
        output      = null;
        electronPos = new List <IVector3> ();
        _logicVals  = new List <bool> ();
        int val = 0;

        for (int i = 0; i < ConstantHandler.Instance.GridLength; i++)
        {
            for (int j = 0; j < ConstantHandler.Instance.GridWidth; j++)
            {
                for (int k = 0; k < ConstantHandler.Instance.GridHeight; k++)
                {
                    GameObject spot;
                    if (_grid.GetComponentObject(new IVector3(i, j, k), out spot))
                    {
                        GridHandler.SpotType _type = _grid.GetComponentType(i, j, k);
                        switch (_type)
                        {
                        case GridHandler.SpotType.INPUT_A:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotateOnClick> ().Direction;
                            input.Add(new InputComponent(new IVector3(i, j, k), dir, _logicInput[0]));
                            _logicVals.Add(_logicInput [0]);
                            electronPos.Add(new IVector3(i, j, k));
                            break;
                        }

                        case GridHandler.SpotType.INPUT_B:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotateOnClick> ().Direction;
                            input.Add(new InputComponent(new IVector3(i, j, k), dir, _logicInput[1]));
                            _logicVals.Add(_logicInput [1]);
                            electronPos.Add(new IVector3(i, j, k));
                            break;
                        }

                        case GridHandler.SpotType.INPUT_C:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotateOnClick> ().Direction;
                            input.Add(new InputComponent(new IVector3(i, j, k), dir, _logicInput[2]));
                            _logicVals.Add(_logicInput [2]);
                            electronPos.Add(new IVector3(i, j, k));
                            break;
                        }

                        case GridHandler.SpotType.WIRE:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotateOnClick> ().Direction;
                            wires.Add(new WireComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.OUTPUT:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotateOnClick> ().Direction;
                            output = new OutputComponent(new IVector3(i, j, k), dir);
                            break;
                        }

                        case GridHandler.SpotType.NOT:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotateOnClick> ().Direction;
                            not.Add(new NOTComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.OR_LEFT:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <SiblingsDir> ().Direction;
                            wires.Add(new WireComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.OR_RIGHT:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <SiblingsDir> ().Direction;
                            wires.Add(new WireComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.OR_CENTRE:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotAndSiblingPosChange>().Direction;
                            or.Add(new ORComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.SPLITTER:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <SplitterRotateOnClick> ().Direction;
                            GridHandler.ComponentDirection sec = spot.GetComponent <SplitterRotateOnClick> ().SecondaryDirection;
                            splitter.Add(new SplitterComponent(new IVector3(i, j, k), dir, sec));
                            break;
                        }

                        case GridHandler.SpotType.AND_CENTRE:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <RotAndSiblingPosChange>().Direction;
                            and.Add(new ANDComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.AND_LEFT:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <SiblingsDir> ().Direction;
                            wires.Add(new WireComponent(new IVector3(i, j, k), dir));
                            break;
                        }

                        case GridHandler.SpotType.AND_RIGHT:
                        {
                            GridHandler.ComponentDirection dir = spot.GetComponent <SiblingsDir> ().Direction;
                            wires.Add(new WireComponent(new IVector3(i, j, k), dir));
                            break;
                        }
                        }
                    }
                }
            }
        }
        if (input.Count < 1)
        {
            Debug.LogError("No inputs detected");
            return;
        }
        if (output == null)
        {
            Debug.LogError("No output detected");
            return;
        }
        MoveElectron();
    }
    private void PerformWireOperation(IVector3 pos, int index)
    {
        foreach (WireComponent wc in wires)
        {
            if (wc.Position == pos)
            {
                bool _tempVal;
                wc.Compute(_logicVals [index], out _tempVal);
                _logicVals [index]  = _tempVal;
                electronPos [index] = wc.MoveElectron();
                Debug.Log("Electron moved through WIRE " + electronPos [index] + " with value =" + _logicVals[index]);
                GridHandler.SpotType type = _grid.GetComponentType(electronPos [index].x, electronPos [index].y, electronPos [index].z);
                switch (type)
                {
                case GridHandler.SpotType.EMPTY:
                    Debug.LogError("Disconnected wire at " + electronPos [index]);
                    break;

                case GridHandler.SpotType.INPUT_A:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.INPUT_B:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.INPUT_C:
                    Debug.LogError("Wire cannot be connected to input wire");
                    break;

                case GridHandler.SpotType.NOT:
                    PerformNotOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.WIRE:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OUTPUT:
                    FinalOutput(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OR_LEFT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OR_RIGHT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.OR_CENTRE:
                    PerformOrOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_CENTRE:
                    PerformAndOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_LEFT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.AND_RIGHT:
                    PerformWireOperation(electronPos [index], index);
                    break;

                case GridHandler.SpotType.SPLITTER:
                    PerformSplitOperation(electronPos [index], index);
                    break;
                }
            }
        }
    }