/**
 * PeerConnection - WebRTC peer connection management
 */

import { EventEmitter } from 'eventemitter3';

export interface PeerConnectionEvents {
    'connection-state-change': (state: RTCPeerConnectionState) => void;
    'ice-candidate': (candidate: RTCIceCandidate) => void;
    'remote-stream': (stream: MediaStream) => void;
    'data-channel': (channel: RTCDataChannel) => void;
}

export class PeerConnection extends EventEmitter<PeerConnectionEvents> {
    private pc: RTCPeerConnection;
    private localStream?: MediaStream;
    private remoteStream?: MediaStream;

    constructor(config?: RTCConfiguration) {
        super();

        this.pc = new RTCPeerConnection(config || {
            iceServers: [
                { urls: 'stun:stun.l.google.com:19302' }
            ]
        });

        this.setupEventHandlers();
    }

    private setupEventHandlers(): void {
        this.pc.onconnectionstatechange = () => {
            this.emit('connection-state-change', this.pc.connectionState);
        };

        this.pc.onicecandidate = (event) => {
            if (event.candidate) {
                this.emit('ice-candidate', event.candidate);
            }
        };

        this.pc.ontrack = (event) => {
            const [stream] = event.streams;
            this.remoteStream = stream;
            this.emit('remote-stream', stream);
        };

        this.pc.ondatachannel = (event) => {
            this.emit('data-channel', event.channel);
        };
    }

    async createOffer(): Promise<RTCSessionDescriptionInit> {
        const offer = await this.pc.createOffer();
        await this.pc.setLocalDescription(offer);
        return offer;
    }

    async createAnswer(): Promise<RTCSessionDescriptionInit> {
        const answer = await this.pc.createAnswer();
        await this.pc.setLocalDescription(answer);
        return answer;
    }

    async setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void> {
        await this.pc.setRemoteDescription(description);
    }

    async addIceCandidate(candidate: RTCIceCandidateInit): Promise<void> {
        await this.pc.addIceCandidate(candidate);
    }

    addLocalStream(stream: MediaStream): void {
        this.localStream = stream;
        stream.getTracks().forEach(track => {
            this.pc.addTrack(track, stream);
        });
    }

    createDataChannel(label: string, options?: RTCDataChannelInit): RTCDataChannel {
        return this.pc.createDataChannel(label, options);
    }

    getConnectionState(): RTCPeerConnectionState {
        return this.pc.connectionState;
    }

    getLocalStream(): MediaStream | undefined {
        return this.localStream;
    }

    getRemoteStream(): MediaStream | undefined {
        return this.remoteStream;
    }

    close(): void {
        this.pc.close();
        this.removeAllListeners();
    }
} 