class Log 
{
    constructor( engine )
    {
        this.engine = engine;

        this.triangles = [];
        var height = 0.5;
        this.triangles.push( new Triangle( new vec3( 0 , height , 0 ) , new vec3( 11 , height , 0 ) , new vec3( 0 , height , 3 ) ) );
        this.triangles.push( new Triangle( new vec3( 0 , height , 3 ) , new vec3( 11 , height , 0 ) , new vec3( 11 , height , 3 ) ) );

        this.tiles = new Array( 33 );
        for ( let i = 0 ; i < this.tiles.length ; ++i )
        {
            this.tiles[i] = {
                x: i%11,
                z: Math.floor( i/11 ),
                obstructed: false
            };
        }

        this.model = Sparrow.ModelLoader.loadGLTF( engine , "models/log.gltf" );
        water.addObject( this.model );

        this.grass = Sparrow.ModelLoader.loadGLTF( engine , "models/test.gltf" );
        water.addObject( this.grass );

        this.hoverQuad = new Sparrow.Plane( engine , new vec3( 0.5 , 0.51 , 0.5 ) , 0.5 , 0.5 );
        this.b_drawHoverQuad = false;
    }

    restart()
    {
        for ( let i = 0 ; i < this.tiles.length ; ++i )
        {
            this.tiles[i].obstructed = false;
        }
        // obstruct the community center
        this.setObstructed( 5 , 1 , true );
    }

    mouseMove( ray )
    {
        if ( !game.b_buildingMode ) return;

        for ( let i = 0 ; i < this.triangles.length ; ++i )
        {
            var result = this.#rayTriangleIntersection( ray , this.triangles[i] );
            if ( result !== false )
            {
                // calculate which tile is hit
                var tileX = Math.floor( result.data[0] );
                var tileZ = Math.floor( result.data[2] );
                this.hoverQuad.setTranslation( tileX+0.5 , 0.51 , tileZ+0.5 );
                this.b_drawHoverQuad = true;
                if ( this.isObstructed( tileX , tileZ ) )
                {
                    this.hoverQuad.setColor( Color3f.RED );
                }
                else
                {
                    this.hoverQuad.setColor( Color3f.GREEN );
                }
                return;
            }
        }
        this.b_drawHoverQuad = false;
    }

    mouseClick( ray )
    {
        if ( !game.b_buildingMode ) return;

        for ( let i = 0 ; i < this.triangles.length ; ++i )
        {
            var result = this.#rayTriangleIntersection( ray , this.triangles[i] );
            if ( result !== false )
            {
                // console.log( "log is hit" );
                // console.log( result );
                // calculate which tile is hit
                var tileX = Math.floor( result.data[0] );
                var tileZ = Math.floor( result.data[2] );
                console.log( "tile: "+tileX+" , "+tileZ );
                if ( !this.isObstructed( tileX , tileZ ) )
                {
                    game.buildingManager.build( tileX , tileZ );
                }
                else
                {
                    console.log( "tile is obstructed" );
                    game.b_buildingMode = false;
                    game.log.b_drawHoverQuad = false;
                }
                return;
            }
        }
        // console.log( "log is NOT hit" );
    }

    draw()
    {
        this.model.draw();
        this.grass.draw();
        if ( this.b_drawHoverQuad ) this.hoverQuad.draw();
    }

    isObstructed( x , z )
    {
        return this.tiles[z*11+x].obstructed;
    }

    setObstructed( x , z , obstructed )
    {
        this.tiles[z*11+x].obstructed = obstructed;
    }

    // copied from nav mesh
    #rayTriangleIntersection( ray , triangle , intersectionPoint )
    {
        const EPSILON = 0.0000001;
        // Vector3D vertex0 = inTriangle->vertex0;
        // Vector3D vertex1 = inTriangle->vertex1;  
        // Vector3D vertex2 = inTriangle->vertex2;
        // Vector3D edge1, edge2, h, s, q;
        // float a, f, u, v;

        // edge1 = vertex1 - vertex0;
        // edge2 = vertex2 - vertex0;
        // h = rayVector.crossProduct(edge2);
        // a = edge1.dotProduct(h);
        var edge1 = vec3.subtract( triangle.v2 , triangle.v1 );
        var edge2 = vec3.subtract( triangle.v3 , triangle.v1 );
        var h = vec3.cross( ray.direction , edge2 );
        var a = vec3.dot( edge1 , h );

        // check if the ray is parallel to the triangle
        if ( Math.abs( a ) < EPSILON )
        {
            console.log( "ray is parallel?" );
            return false;
        }
    
        // f = 1.0 / a;
        // s = rayOrigin - vertex0;
        // u = f * s.dotProduct(h);
        var f = 1/a;
        var s = vec3.subtract( ray.origin , triangle.v1 );
        var u = f * vec3.dot( s , h );
    
        if ( u < 0.0 || u > 1.0 ) return false;
    
        // q = s.crossProduct(edge1);
        // v = f * rayVector.dotProduct(q);
        var q = vec3.cross( s , edge1 );
        var v = f * vec3.dot( ray.direction , q );
    
        if ( v < 0.0 || u + v > 1.0 ) return false;
    
        // At this stage we can compute t to find out where the intersection point is on the line.
        // float t = f * edge2.dotProduct(q);
        var t = f * vec3.dot( edge2 , q );
    
        if ( t > EPSILON ) // ray intersection
        {
            // outIntersectionPoint = rayOrigin + rayVector * t;
            var intersectionPoint = vec3.add( ray.origin , vec3.scale( ray.direction , t ) );
            // intersectionPoint.print();
            return intersectionPoint;
        }
        // This means that there is a line intersection but not a ray intersection.
        else
        {
            console.log( "ray is behind?" );
            return false;
        }
    }
}