class RemoteCamera extends this.OS.application.BaseApplication
    constructor: ( args ) ->
        super "RemoteCamera", args
    
    main: () ->
        
        @decoder = new Worker("pkg://RemoteCamera/decoder.js".asFileHandle().getlink())
        
        @decoder.onmessage = (e) =>
            @paint e.data
            
        @decoder.postMessage {libjpeg: "pkg://libjpeg/jpg.js".asFileHandle().getlink()}
        
        @mute = false
        @player = @find "player"
        
        @qctl = @find "qctl"
        
        @fpsctl = @find "fpsctl"
        
        
        
        @cam_setting = {
            w: 640,
            h: 480,
            fps: 10,
            quality: 60
        }
        
        fps = []
        for i in [5..30] by 5
            fps.push {
                text: "#{i}",
                value: i
            }
        @fpsctl.data = fps
        @fpsctl.selected = @cam_setting.fps/5 -1
        
        @fpsctl.onlistselect = (e) =>
            return if @mute
            @cam_setting.fps = e.data.item.data.value
            @setCameraSetting()
        
        @qctl.value = @cam_setting.quality
        
        
        @resoctl = @find "resoctl"
        
        @resoctl.data = [
            {
                text: __("320x240"),
                mode: "qvga"
            },
            {
                text: __("640x480"),
                selected: true,
                mode: "vga"
            },
            {
                text: __("800x600"),
                mode: "svga"
            },
            {
                text: __("1024x760"),
                mode: "hd"
            },
            {
                text: __("1920×1080"),
                mode: "fhd"
            }
        ]
        @resoctl.onlistselect = (e) =>
            return if @mute
            switch e.data.item.data.mode
                when "qvga"
                    @cam_setting.w = 320
                    @cam_setting.h = 240
                when "vga"
                    @cam_setting.w = 640
                    @cam_setting.h = 480
                when "svga"
                    @cam_setting.w = 800
                    @cam_setting.h = 600
                when "hd"
                    @cam_setting.w = 1024
                    @cam_setting.h = 768
                when "fhd"
                    @cam_setting.w = 1920
                    @cam_setting.h = 1080
            @setCameraSetting()
        
        @qctl.onvaluechange = (e) =>
            return if @mute
            @cam_setting.quality = e.data
            @setCameraSetting()
        
        return @notify __("Antunnel service is not available") unless Antunnel.tunnel
        if not @setting.channel
            @requestChannel()
        else
            @openSession()
    
    requestChannel: () ->
        @openDialog "PromptDialog", {
            title: __("Enter camera channel"),
            label: __("Please enter camera channel name")
        }
        .then (v) =>
            @setting.channel = v
            return @openSession() unless @sub
            @sub.onclose = (e) =>
                @openSession()
            @sub.close()
    
    paint: (msg) ->
        # console.log msg
        data = new Uint8Array msg.pixels
        ctx = @player.getContext "2d", { alpha: false }
        @player.width = msg.w
        @player.height = msg.h
        imgData = ctx.createImageData  msg.w, msg.h
        imgData.data.set data
        ctx.putImageData imgData, 0, 0
    
    menu: () ->
        {
            text: "__(Option)",
            nodes: [
                { text: "__(Camera channel)" }
            ],
            onchildselect: (e) => @requestChannel()
        }
    
    openSession: () ->
        return unless Antunnel
        return unless @setting.channel
        @tunnel = Antunnel.tunnel
        @sub = new Antunnel.Subscriber(@setting.channel)
        @sub.onopen = () =>
            console.log("Subscribed to camera channel")
        
        @sub.onerror = (e) =>
            @error __("Error: {0}", new TextDecoder("utf-8").decode(e.data)), e
            #@sub = undefined
        @sub.onctrl = (e) =>
            @cam_setting.w = Antunnel.Msg.int_from(e.data,0)
            @cam_setting.h = Antunnel.Msg.int_from(e.data,2)
            @cam_setting.fps = e.data[4]
            @cam_setting.quality = e.data[5]
            @mute = true
            @qctl.value = @cam_setting.quality
            res = "#{@cam_setting.w}x#{@cam_setting.h}"
            switch res
                when "320x240"
                    @resoctl.selected = 0
                when "640x480"
                    @resoctl.selected = 1
                when "800x600"
                    @resoctl.selected = 2
                when "1024x768"
                    @resoctl.selected = 3
                when "1920x1080"
                    @resoctl.selected = 4
            @fpsctl.selected = @cam_setting.fps/5 -1
            @mute = false
            
        @sub.onmessage =  (e) =>
            return unless @decoder
            @decoder.postMessage e.data.buffer, [e.data.buffer]
            
        @sub.onclose = () =>
            @sub = undefined
            @notify __("Unsubscribed to the camera service")
            return @quit()
        Antunnel.tunnel.subscribe @sub
    
    cleanup: () ->
        @sub.close() if @sub
        @decoder.terminate() if @decoder
    
    setCameraSetting: () ->
        return unless @sub
        arr = new Uint8Array(6)
        arr.set Antunnel.Msg.bytes_of(@cam_setting.w), 0
        arr.set Antunnel.Msg.bytes_of(@cam_setting.h), 2
        arr[4] = @cam_setting.fps
        arr[5] = @cam_setting.quality
        @sub.send Antunnel.Msg.CTRL, arr

RemoteCamera.singleton = true

this.OS.register "RemoteCamera", RemoteCamera