import java.util.*;
public class Solution {
    public static List<List<Integer>> matrixMultiplication(List<List<List<Integer>>> matrices) {

        List<List<Integer>> finalMatrix = new ArrayList<List<Integer>>();

        List<Integer> temp = new ArrayList<Integer>();

        int rowsNextMatrix=0;
        int size=0;
        int matricesSize=matrices.size();
        int posInList=0;
        int numElementsInList=0;
        int counter=0;
        int i;
        int position=0;
        boolean hasTransposed=false;
        List<List <Integer>> matrix;
        boolean hasStartMatrix=true;
        boolean hasPerformedValidation=false;
        int numElementsInRow=0;
        int rowNumberNextMatrix=0;
        int matrixNumber=0;
        int numElementInNextMatrixRow;

        //I am using this size based on principle that
        //number columns Matrix A needs to be equal 
        //number rows Matrix B
        //This is easiest way to ascertain a suitable dimension
        //of Matrix B
        //really this would need to be in a try and catch statement should there only be one matrix!
        int []matrixValue = new int[matrices.get(1).size()];
        
        //The following structure will ensure that
        //each each matrix can be obtained from the matrices
        //We have to remember that inner Lists can still be accessed via their index locations. This can be obtained via .get
        //We know that similar to other transposing matrix challenge, we can obtain the size (matrices) which will output the number of elements..
        //We know in this case this deals with List<List<Integer>>
        //We can now formulate a do while loop which would process the List<List<Integer>> within matrices until it reaches the size of matrices.

        do
        {
            matrix=matrices.get(counter);
            System.out.println("Matrix" +"("+counter+"): "+ matrix); 

        for (List<Integer> ee: matrix)
        {
            //Since a new row on Matrix A causes Matrix B to start initial position. Not 100% sure its right location.
            numElementInNextMatrixRow=0;
            System.out.println("RESET first row on forthcoming matrix");    

            for (int k: ee)
            {
                System.out.println("Element: " + k);

                //I am now choosing to look ahead at the next matrix as soon as a number appears on the screen.
                //The only exception of course is the final matrix since it would have been processed by penultimate matrix.
                if(counter!=matricesSize-1)
                {
                
                //In this matrix we know that numbers are retrieved left to right.
                //I am going to attempt completing the multiplication in a similar manner to a human.
                /*
                [1, 2, 3] 
                [4, 5, 6]

                [7,    8] 
                [9,   10]
                [11, 12]
                */

            //This processes next matrix
            //we know that whilst it processes row 1 of Matrix A
            //it will ALWAYS be on column 1 of Matrix B
            for (List<Integer> rows: matrices.get((counter+1)))
            {
                System.out.println("REACH!!!!: " + "row next matrix: " + rowNumberNextMatrix + "num elem: " + numElementsInRow);

                if(rowNumberNextMatrix==numElementsInRow)
                {                  
                    System.out.println("**********");
                    //we then need to ensure that for forthcoming matrix we are looking at the correct row
                    for (int p: rows)
                    {
                        

            if (numElementInNextMatrixRow==numElementsInRow)
            {
                matrixValue[0]=matrixValue[0] + (k*p);
                System.out.println("VALUE: " + matrixValue[0] + "\t"+ k + "x" + p);

                rowNumberNextMatrix++;
                System.out.println("INCREASE ROW NUMBER NEXT MATRIX");
                
                break;
            }

            //we need to introduce another counter since we know that for each row of Matrix A it will perform operation on each column on Matrix B.
            //This variable has to be reset once it has performed
            //row of the previous Matrix otherwise indexing will be compromised severely
            numElementInNextMatrixRow++;
            
                    }

                    
                }                
            }
            



                    //if (ee.size())

                }

                if (matrixNumber<counter && hasStartMatrix)
                {
                    System.out.println("This is first integer in next matrix: " + k);
                    hasStartMatrix=false;   
                }

                numElementsInList++;
                numElementsInRow++;
                
            }
            

            //Using this technique will also ensure that I can check if the matrix is valid dimension and terminate the application
            //WE KNOW THAT NUMBER columns in Matrix A should match rows Matrix B

            if(counter!=(matricesSize-1) && !hasPerformedValidation)
            {
                for (List<Integer> rows: matrices.get((counter+1)))
                {
                    rowsNextMatrix++;
                }

                    if (numElementsInRow!=rowsNextMatrix)
                    {
            System.out.println("columns in Matrix A" + "("+numElementsInRow+")"+ "should match rows Matrix B " +  "("+rowsNextMatrix+")");
                        System.exit(0);
                    }
                    else
                    {
                        System.out.println("columns in Matrix A " + "("+numElementsInRow+")" + " rows Matrix B: " + "("+rowsNextMatrix+")");
                    }
                    hasPerformedValidation=true;
            }

            numElementsInRow=0;

            //break;
        }
        matrixNumber=counter;
        counter++;
        hasStartMatrix=true;
        hasPerformedValidation=false;
        rowsNextMatrix=0;
        rowNumberNextMatrix=0;

        }while (counter<matricesSize);

        System.out.println("num elements: " + numElementsInList);

        return finalMatrix;
    }
}

