let buildings = [];

// --- Building Data---
const buildingTypes = {
    house: {
        geometry: new THREE.BoxGeometry(4, 6, 4),
        material: new THREE.MeshLambertMaterial({ color: 0x87CEEB}),
        description: "Residential House", consumption: "Low Energy, Water", generation: "None", iot: "Smart Thermostat, Smart Lights"
    },
    factory: {
        geometry: (() => {
            const shape = new THREE.Shape().moveTo(0, 0).lineTo(0, 6).lineTo(8, 6).lineTo(8, 8).lineTo(10, 8).lineTo(10, 0).lineTo(0, 0);
            return new THREE.ExtrudeGeometry(shape, { depth: 12, bevelEnabled: false });
        })(),
        material: new THREE.MeshLambertMaterial({ color: 0xB22222}),
        description: "Manufacturing Plant", consumption: "High Energy, Industrial Resources", generation: "Goods, Waste Heat", iot: "Process Sensors, Automated Controls"
    },
    office: {
        geometry: new THREE.BoxGeometry(6, 10, 6),
        material: new THREE.MeshLambertMaterial({ color: 0xFFFFFF }),
        description: "Office Building", consumption: "Medium Energy, Data", generation: "Services, Data", iot: "BMS, Occupancy Sensors"
    },
    shop: {
        geometry: new THREE.BoxGeometry(8, 4, 6),
        material: new THREE.MeshLambertMaterial({ color: 0xd8d400 }),
        description: "Retail Shop", consumption: "Medium Energy, Goods", generation: "Retail Sales", iot: "POS System, Smart Shelves"
    }
};

function initBuildings() {
    createBuilding('house', new THREE.Vector3(-9, 0, 24), 'H01', 'data/H01.csv', 'assets/models/building1.glb');
    createBuilding('factory', new THREE.Vector3(48, 0, -49), 'H02', 'data/H02.csv', 'assets/models/factory.glb'); // ExtrudeGeometry origin is at bottom
    createBuilding('office', new THREE.Vector3(-38, 0, -12), 'H03', 'data/H03.csv', 'assets/models/predio1.glb');
    createBuilding('shop', new THREE.Vector3(-5, 0, -5), 'H04', 'data/H04.csv', 'assets/models/store1.glb', Math.PI / 2);
    createBuilding('house', new THREE.Vector3(-5, 0, 40), 'H05', 'data/H05.csv', 'assets/models/building2.glb');
    createBuilding('house', new THREE.Vector3(6, 0, 24), 'H06', 'data/H06.csv', 'assets/models/building1.glb');
    createBuilding('house', new THREE.Vector3(-37, 0, 30), 'H07', 'data/H07.csv', 'assets/models/house1.glb');
    createBuilding('house', new THREE.Vector3(-34, 0, 9), 'H08', 'data/H08.csv', 'assets/models/store4.glb', -Math.PI / 2);
    createBuilding('house', new THREE.Vector3(19, 0, -20), 'H09', 'data/H09.csv', 'assets/models/store2.glb', Math.PI / 2);
    createBuilding('house', new THREE.Vector3(36, 0, 6), 'H10', 'data/H10.csv', 'assets/models/store5.glb');
    createBuilding('house', new THREE.Vector3(34, 0, -19), 'H11', 'data/H11.csv', 'assets/models/store3.glb', Math.PI);
    createBuilding('house', new THREE.Vector3(-21, 0, -18), 'H12', 'data/H12.csv', 'assets/models/predio2.glb');
    createBuilding('house', new THREE.Vector3(-5, 0, -20), 'H13', 'data/H13.csv', 'assets/models/predio3.glb');
    createBuilding('house', new THREE.Vector3(-7, 0, -48), 'H14', 'data/H14.csv', 'assets/models/predio4.glb');
    renderer.domElement.addEventListener('pointerdown', function(event) {
        // Calculate mouse position in normalized device coordinates
        const rect = renderer.domElement.getBoundingClientRect();
        const mouse = new THREE.Vector2(
            ((event.clientX - rect.left) / rect.width) * 2 - 1,
            -((event.clientY - rect.top) / rect.height) * 2 + 1
        );
    
        raycaster.setFromCamera(mouse, camera);
        const intersects = raycaster.intersectObjects(interactableObjects);
    
        if (intersects.length > 0) {
            const mesh = intersects[0].object;
            if (mesh.material && mesh.material.name && mesh.material.name.toLowerCase().includes("vetro")) {
                enableWindowLight(mesh);
            }
        }
    });
}

function enableWindowLight(windowMesh) {
    // If light is already on, turn it off
    if (windowMesh.userData.lightOn) {
        if (windowMesh.userData.lightOn.parent) {
            windowMesh.userData.lightOn.parent.remove(windowMesh.userData.lightOn);
        }
        windowMesh.userData.lightOn = null;
        // Optionally, reset window glow
        if (windowMesh.material) {
            windowMesh.material.emissive = new THREE.Color(0x000000);
            windowMesh.material.emissiveIntensity = 0;
        }
        return;
    }

    // Create a warm point light just inside the window
    const light = new THREE.PointLight(0xdbb108, 2, 20);
    // Place the light slightly inside the window (adjust as needed)
    const bbox = new THREE.Box3().setFromObject(windowMesh);
    const center = bbox.getCenter(new THREE.Vector3());
    light.position.copy(center);
    // Optionally, offset the light a bit inward
    light.position.y += 1;

    // Attach the light to the window's parent group (the building)
    if (windowMesh.parent) {
        scene.add(light);
    }
    windowMesh.userData.lightOn = light;
    if (windowMesh.material) {
        windowMesh.material.color.set(0x66aaff)
        windowMesh.material.emissive = new THREE.Color(0xebb104);
        windowMesh.material.emissiveIntensity = 1;
    }
}

// --- Building Creation Function ---
function createBuilding(type, position, id, csvPath, modelPath, rotation) {
    const buildingData = buildingTypes[type];
    if (!buildingData) { console.warn(`Building type "${type}" not found.`); return null; }

    if (modelPath) {
        const loader = new THREE.GLTFLoader();
        loader.load(modelPath, function (gltf) {
            const group = gltf.scene;
            
            group.position.copy(position);
            if (rotation){
                group.rotation.y = rotation;
            }
            group.userData = { id, type, ...buildingData, csvPath };
            group.traverse(function (child) {
                if (child.isMesh) {
                    child.castShadow = true;
                    child.receiveShadow = true;
                    child.userData.parentGroup = group;
                    interactableObjects.push(child);
                    // Make windows less transparent
                    if (child.material && child.material.name && child.material.name.toLowerCase().includes("vetro")) {
                        child.material.thickness = 1;
                        child.material.opacity = 1; // or 1 for fully opaque
                        child.material.transparent = true; // or false if you want no transparency
                        child.material.transmission = 0.01;
                    }
                }
            });
            buildings.push(group);
            scene.add(group);
            if (csvPath) loadBuildingCSV(group, csvPath);
        }, undefined, function (error) {
            console.error('Error loading model:', error);
        });
    } else {
        const mesh = new THREE.Mesh(buildingData.geometry, buildingData.material);
        mesh.position.copy(position);
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        mesh.userData = { id, type, ...buildingData, csvPath }; // Store csvPath
        scene.add(mesh);
        buildings.push(mesh);
        interactableObjects.push(mesh);
        if (csvPath) loadBuildingCSV(mesh, csvPath);
        return mesh;
    }
}

function loadBuildingCSV(building, csvPath) {
    Papa.parse(csvPath, {
        download: true,
        header: true,
        dynamicTyping: true,
        complete: function (results) {
            building.userData.energyData = results.data; // Array of rows
            // Optionally, set initial values
            if (results.data.length > 0) {
                updateBuildingEnergy(building, 0); // Set to first row
            }
        }
    });
}

// Helper to update building's current energy values by row index (e.g., time step)
function updateBuildingEnergy(building, rowIndex) {
    const data = building.userData.energyData;
    if (!data || !data[rowIndex]) return;
    const row = data[rowIndex];
    building.userData.generation = row.Generation;
    building.userData.consumption = row.Consumption;
    building.userData.devices = {
        Time: row.Time,
        AC1: row.AC1,
        AC2: row.AC2,
        AC3: row.AC3,
        AC4: row.AC4,
        WaterHeater: row['Water heater'],
        TV: row.TV,
        Microwave: row.Microwave,
        Kettle: row.Kettle,
        Lighting: row.Lighting,
        Refrigerator: row.Refrigerator,
        FlexibleLoad: row['Flexible Load'],
        RigidLoad: row['Rigid Load']
    };
}

function updateAllBuildingsForTimeStep(rowIndex) {
    buildings.forEach(obj => {
        if (obj.userData.energyData) {
            updateBuildingEnergy(obj, rowIndex);
        }
    });
}

function updateBuildings() {
    const rowIndex = getCurrentRowIndex();

    if (rowIndex !== lastUpdateRowIndex) {
        //updateAllBuildingsForTimeStep(rowIndex);
        lastUpdateRowIndex = rowIndex;
    }
}