import { Injectable } from '@angular/core';
import { SSE } from 'sse.js';
import { Observable, Subject } from 'rxjs';

export type ExecutionMessage = {
  type: 'stdout' | 'stderr' | 'exit';
  text: string;
};

@Injectable({
  providedIn: 'root',
})
export class CodeExecutionService {
  private apiUrl = 'http://localhost:3000/run';
  private resultSubject = new Subject<ExecutionMessage>();

  constructor() {}

  executeCode(code: string, language: string) {
    const sse = new SSE(this.apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'text/event-stream',
      },
      payload: JSON.stringify({ code, language }),
    });

    sse.addEventListener('message', (event: MessageEvent<string>) => {
      const result = event.data;

      // @ts-expect-error The type is not declared although present
      const type = event.id;
      const text = decodeURIComponent(result.replace(/%00/g, ''));
      if (type === 'end') {
        sse.close();
      }
      this.resultSubject.next({ type, text });
    });
  }

  getResult(): Observable<ExecutionMessage> {
    return this.resultSubject.asObservable();
  }
}
