import { Utils } from "../util/Utils";
import { CastSessionVO } from "../vo/cast/CastSessionVO";
import { ControllerDeviceVO } from "../vo/device/ControllerDeviceVO";
import { CastSlot } from "../vo/report/CastSlot";
import { DisplayReportVO } from "../vo/report/DisplayReportVO";

export class GlobalCache {
    private readonly onlineDisplays: Map<string, number>;//显示端id为key，显示端code为value
    private readonly connectedDisplays: Map<string, number>;//控制端guid为key，显示端code为value
    private readonly displayReports: Map<number, DisplayReportVO>;//显示端code为key，实体为value
    private readonly castSessions: Map<number, CastSessionVO>;//显示&控制终端均使用，castSessionId为key
    private readonly controllers: Map<string, ControllerDeviceVO>;//控制终端&云端使用，guid为key

    constructor() {
        this.onlineDisplays = new Map();
        this.connectedDisplays = new Map();
        this.displayReports = new Map();
        this.castSessions = new Map();
        this.controllers = new Map();
    }

    public addOnlineDisplay(displayDeviceId: string, displayCode: number, report: DisplayReportVO): void {
        this.onlineDisplays.set(displayDeviceId, displayCode);
        this.displayReports.set(displayCode, report);
    }

    public removeOnlineDisplay(displayDeviceId: string, displayCode: number): void {
        this.displayReports.delete(displayCode);
        this.onlineDisplays.delete(displayDeviceId);
    }

    public clearOnlineDisplay(): void {
        this.displayReports.clear();
        this.onlineDisplays.clear();
    }

    public getOnlineDisplayByID(displayDeviceId: string): DisplayReportVO | null {
        let displayCode: number | undefined = this.onlineDisplays.get(displayDeviceId)
        if (undefined === displayCode || null === displayCode) {
            return null;
        }
        return this.getOnlineDisplayByCode(displayCode!);
    }

    public getOnlineDisplayByCode(displayCode: number): DisplayReportVO | null {
        let ori: DisplayReportVO | undefined = this.displayReports.get(displayCode);
        if (undefined === ori || null === ori) {
            return null;
        }
        return DisplayReportVO.copy(ori!);
    }

    public addConnectedDisplay(controllerGuid: string, displayCode: number, report: DisplayReportVO): void {
        this.connectedDisplays.set(controllerGuid, displayCode);
        this.onlineDisplays.set(report.displayDevice.displayDeviceId, displayCode);
        this.displayReports.set(displayCode, report);
    }

    public removeConnectedDisplay(controllerGuid: string, displayCode: number): void {
        this.connectedDisplays.delete(controllerGuid);
    }

    public clearConnectedDisplay(): void {
        this.connectedDisplays.clear();
    }

    public getConnectedDisplayByID(controllerGuid: string): DisplayReportVO | null {
        let displayCode: number | undefined = this.connectedDisplays.get(controllerGuid);
        if (undefined === displayCode || null === displayCode) {
            return null;
        }
        return this.getConnectedDisplayByCode(displayCode);
    }

    public getConnectedDisplayByCode(displayCode: number): DisplayReportVO | null {
        return this.getOnlineDisplayByCode(displayCode);
    }

    public addCastSession(castSessionId: number, session: CastSessionVO): void {
        this.castSessions.set(castSessionId, session);
    }

    public removeCastSession(castSessionId: number): void {
        this.castSessions.delete(castSessionId);
    }

    public castSessionValues(): IterableIterator<CastSessionVO> {
        return this.castSessions.values();
    }

    public getCastSession(castSessionId: number): CastSessionVO | null {
        let session: CastSessionVO = new CastSessionVO();
        if (0 === this.castSessions.size || !this.castSessions.has(castSessionId)) {
            return null;
        }
        let ori: CastSessionVO | undefined = this.castSessions.get(castSessionId);
        session.castSessionId = ori!.castSessionId;
        session.displayCode = ori!.displayCode;
        session.guid = ori!.guid;
        session.castType = ori!.castType;;
        session.castProtocol = ori!.castProtocol;
        return session;
    }

    public clearCastSessions(): void {
        this.castSessions.clear();
    }

    public addControllerDevice(guid: string, device: ControllerDeviceVO): void {
        this.controllers.set(guid, device);
    }

    public removeControllerDevice(guid: string): void {
        this.controllers.delete(guid);
    }

    public getControllerDevice(guid: string): ControllerDeviceVO | null {
        let copy: ControllerDeviceVO = new ControllerDeviceVO();
        if (0 === this.controllers.size || !this.controllers.has(guid)) {
            return null;
        }
        let ori: ControllerDeviceVO | undefined = this.controllers.get(guid);
        copy.guid = ori!.guid;
        copy.controllerDeviceType = ori!.controllerDeviceType;
        copy.ip = ori!.ip;
        copy.gateway = ori!.gateway;
        copy.mask = ori!.mask;
        copy.outIp = ori!.outIp;
        return copy;
    }

}