export class FileChangeNotificationService {
    public rpc: RPC = new RPC
    public events: Leaf.EventEmitter<"change"> = new Leaf.EventEmitter()
    public connector = new ConnectionKeepProcedure(this.rpc)
    constructor(public path: string) {
        this.connector.start(path)
        this.rpc.remoteEvents.listenBy(this, "change", () => {
            this.events.emit("change")
        })
    }
}
class RPC extends Leaf.RPCComposer {
}

class ConnectionKeepProcedure extends Leaf.States<string, string> {
    constructor(public rpc: Leaf.RPCComposer) {
        super()
        this.debug()
    }
    protected data: {
        connection: WebSocket
    }
    public path: string = window.location.toString().replace("http", "ws")
    start(path?: string) {
        if (path) {
            this.path = path
        }
        if (this.state === "void") {
            this.setState("connecting")
        }
    }
    atConnecting(stale) {
        this.data.connection = new WebSocket(this.path)
        let openHandler = () => {
            this.data.connection.removeEventListener("close", closeHandler)
            this.setState("setup")
        }
        let closeHandler = () => {
            if (stale()) return
            this.data.connection.removeEventListener("open", openHandler)
            this.data.connection.removeEventListener("close", closeHandler)
            this.setState("waitReconnect")
        }
        this.data.connection.addEventListener("open", openHandler)
        this.data.connection.addEventListener("close", closeHandler)

    }
    atSetup(stale) {
        let conn = new Leaf.RPCBrowserWebSocketConnection(this.data.connection)
        this.rpc.setConnection(conn)
        this.setState("working")
    }
    atWorking(stale) {
        let closeHandler = () => {
            if (stale()) return
            this.data.connection.removeEventListener("close", closeHandler)
            this.setState("close")
        }
        this.data.connection.addEventListener("close", closeHandler)
    }
    atClose(stale) {
        this.setState("waitReconnect")
    }
    atWaitReconnect(stale) {
        setTimeout(() => {
            if (stale()) return
            this.setState("connecting")
        }, this.waitInterval)
    }
    public waitInterval: number = 1000
}
