/**
 * Railtrack Pro - Track Piece System
 * Defines track geometries and placement logic
 * @author Railtrack Pro Development Team
 */

class TrackPiece {
    constructor(type, position, rotation) {
        this.type = type; // 'straight', 'curved', 'junction', 'signal'
        this.id = position ? Math.floor(Math.random() * 10000) : null;
        this.position = position || new THREE.Vector3(0, 0, 0);
        this.rotation = rotation || new THREE.Vector3(0, Math.PI / 2, 0);
        this.connections = [];
        this.geometry = null;
        this.material = null;
        this.mesh = null;
    }

    /**
     * Create track piece in scene
     */
    create(scene) {
        this.geometry = this.getGeometry();
        this.material = new THREE.MeshStandardMaterial({
            color: 0x888888,
            roughness: 0.6,
            metalness: 0.4
        });
        
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.mesh.position.copy(this.position);
        this.mesh.rotation.copy(this.rotation);
        this.mesh.castShadow = true;
        this.mesh.receiveShadow = true;
        this.mesh.userData = { type: 'track', id: this.id, piece: this };
        
        scene.add(this.mesh);
        return this;
    }

    /**
     * Get geometry based on track type
     */
    getGeometry() {
        switch (this.type) {
            case 'straight':
                return new THREE.BoxGeometry(1, 0.3, 2);
            case 'curved':
                return this.createCurvedGeometry();
            case 'junction':
                return this.createJunctionGeometry();
            case 'signal':
                return this.createSignalGeometry();
            default:
                return new THREE.BoxGeometry(1, 0.3, 2);
        }
    }

    /**
     * Create curved track geometry
     */
    createCurvedGeometry() {
        const points = [];
        const segments = 20;
        const radius = 2;
        
        for (let i = 0; i <= segments; i++) {
            const angle = (i / segments) * Math.PI;
            const x = Math.sin(angle) * radius;
            const z = -Math.cos(angle) * radius + radius;
            points.push(new THREE.Vector3(x, 0, z));
        }
        
        const curve = new THREE.CatmullRomCurve3(points);
        const geometry = new THREE.TubeGeometry(curve, segments, 0.5, 8, false);
        return geometry;
    }

    /**
     * Create junction track geometry (T-junction)
     */
    createJunctionGeometry() {
        const group = new THREE.Group();
        
        // Main stem
        const stem = new THREE.Mesh(
            new THREE.BoxGeometry(1, 0.3, 2),
            this.material
        );
        stem.position.set(0, 0, 1);
        
        // Top branch
        const top = new THREE.Mesh(
            new THREE.BoxGeometry(1, 0.3, 2),
            this.material
        );
        top.position.set(0, 0, -1);
        
        // Side branch
        const side = new THREE.Mesh(
            new THREE.BoxGeometry(2, 0.3, 1),
            this.material
        );
        side.position.set(0, 0, 0);
        
        group.add(stem, top, side);
        
        const geometry = new THREE.Group(group);
        return geometry;
    }

    /**
     * Create signal track piece
     */
    createSignalGeometry() {
        const group = new THREE.Group();
        
        // Signal pole
        const pole = new THREE.Mesh(
            new THREE.CylinderGeometry(0.1, 0.1, 1.5),
            new THREE.MeshStandardMaterial({ color: 0x333333 })
        );
        pole.position.set(0, 0.75, 0);
        
        // Signal lights
        const lightBox = new THREE.Mesh(
            new THREE.BoxGeometry(0.3, 0.2, 0.1),
            new THREE.MeshStandardMaterial({ color: 0xff0000 })
        );
        lightBox.position.set(0, 1.5, 0);
        
        // Track base
        const base = new THREE.Mesh(
            new THREE.BoxGeometry(1, 0.3, 1),
            this.material
        );
        base.position.set(0, 0, 0);
        
        group.add(base, pole, lightBox);
        
        const geometry = new THREE.Group(group);
        return geometry;
    }

    /**
     * Get connection points for track joining
     */
    getConnectionPoints() {
        const points = [];
        switch (this.type) {
            case 'straight':
                points.push(new THREE.Vector3(0, 0, -1));
                points.push(new THREE.Vector3(0, 0, 1));
                break;
            case 'curved':
                points.push(new THREE.Vector3(0, 0, -2));
                points.push(new THREE.Vector3(2, 0, 0));
                break;
            case 'junction':
                points.push(new THREE.Vector3(0, 0, -2));
                points.push(new THREE.Vector3(0, 0, 2));
                points.push(new THREE.Vector3(-2, 0, 0));
                points.push(new THREE.Vector3(2, 0, 0));
                break;
        }
        return points;
    }
}

/**
 * Track type configuration
 */
const TrackConfig = {
    types: {
        straight: { name: 'Straight Track', color: 0x888888, cost: 10 },
        curved: { name: 'Curved Track', color: 0x888888, cost: 15 },
        junction: { name: 'Junction', color: 0x888888, cost: 25 },
        signal: { name: 'Signal', color: 0xff0000, cost: 30 }
    },
    placement: {
        snapDistance: 0.1,
        maxConnections: 4
    }
};

// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
    module.exports = { TrackPiece, TrackConfig };
}
