# -*- coding: utf-8 -*-

########################################
# HXbot camera control module          #
# EoF 2016 EoF@itphx.ru                #
########################################

import subprocess
import threading
#import select
import time
import sys
import os.path as path
import HX


class HXcamClass():

    def __init__(self):
        super(HXcamClass, self).__init__()

        self.__e = None
        self.__t = None

        self.mcam = None
        self.rcam = None
        self.mmic = None
        self.rvid = None

        self.is_running = False

        # Subprocess states
        # 0 - Not running
        # 1 - Running
        # 2 - Error
        # 3 - Device not found
        self.mcam_state = HX.CAM_STATE_STP
        self.rvid_state = HX.CAM_STATE_STP
        self.rcam_state = HX.CAM_STATE_STP
        self.mmic_state = HX.CAM_STATE_STP

        self.mcam_wrn_count = 0
        self.rcam_wrn_count = 0
        self.mmic_wrn_count = 0

    def start(self):
        self.__e = threading.Event()
        self.__t = threading.Thread(target=self.__process, args=(self.__e, ))

        self.mcam_start()
        #self.rcam_start()
        self.mmic_start()

        self.__t.start()

        self.is_running = True

    def stop(self):
        self.__e.set()
        self.__t.join()
        self.__e = None
        self.__t = None

        self.mcam_stop()
        #self.rcam_stop()
        self.mmic_stop()

        self.is_running = False

    def restart(self):
        if self.is_running:
            self.__stop()
        self.__start()

    def test(self):
        #import time
        #import sys
        #import shlex
        #string = ""
        #args = shlex.split(string)
        #print(args)
        #sys.exit()
        pass

    def mcam_start(self):
        # cvlc 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15'
        # --sout '#rtp{sdp=rtsp://:8554/video}' -v --live-caching 50
        if path.exists('/dev/video0'):
            arg = 'v4l2:///dev/video0:chroma=H264:width=1280:height=720:fps=15'
        elif path.exists('/dev/video1'):
            arg = 'v4l2:///dev/video1:chroma=H264:width=1280:height=720:fps=15'
        else:
            self.mcam_state = HX.CAM_STATE_ERR
            return

        self.mcam = subprocess.Popen(
            args=['/usr/bin/cvlc',
                  arg,
                  '--sout', '#rtp{sdp=rtsp://:8554/video}',
                  '--live-caching', '50', 'vlc://quit'],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL)

        self.mcam_state = HX.CAM_STATE_RUN

    def mcam_stop(self):
        if self.mcam_state != HX.CAM_STATE_ERR:
            self.mcam.terminate()
            self.mcam_state = HX.CAM_STATE_STP

    def rcam_start(self):
        # raspivid -t 0 -n -w 1280 -h 720 -fps 15 -o - |
        # cvlc -v stream:///dev/stdin
        # --sout '#rtp{sdp=rtsp://:8555/video}' :demux=h264
        self.rvid = subprocess.Popen(
            args=['raspivid', '-t', '0', '-n', '-w', '1280', '-h', '720',
                  '-fps', '15', '-o', '-'],
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL)

        self.rcam = subprocess.Popen(
            args=['cvlc', 'stream:///dev/stdin', '--sout',
                  '#rtp{sdp=rtsp://:8555/video}', ':demux=h264',
                  '--live-caching', '50', 'vlc://quit'],
            stdin=self.rvid.stdout,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL)

        self.rcam_state = HX.CAM_STATE_RUN

    def rcam_stop(self):
        if self.rcam_state != HX.CAM_STATE_ERR:
            self.rvid.terminate()
            self.rcam.terminate()
            self.rcam_state = HX.CAM_STATE_STP

    def mmic_start(self):
        # cvlc -v 'alsa://hw:1,0'
        # --sout '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}
        # :rtp{sdp=rtsp://:8556/audio}'
        self.mmic = subprocess.Popen(
            args=['cvlc', 'alsa://hw:0,0', '--sout',
                  '#transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}' +
                  ':rtp{sdp=rtsp://:8556/audio}',
                  '--live-caching', '500', 'vlc://quit'],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL)

        self.mmic_state = HX.CAM_STATE_RUN

    def mmic_stop(self):
        if self.mmic_state != HX.CAM_STATE_ERR:
            self.mmic.terminate()
            self.mmic_state = HX.CAM_STATE_STP

    def __process(self, stopRequest):
        # Process loop
        while not stopRequest.is_set():
            # Main Camera
            if self.mcam_state != HX.CAM_STATE_ERR:
                if self.mcam.poll() is not None:
                    self.mcam_start()

                    if self.mcam_state != HX.CAM_STATE_WRN:
                        self.mcam_wrn_count += 1

                    if self.mcam_wrn_count >= HX.CAM_MAX_WRN_COUNT:
                        self.mcam_state = HX.CAM_STATE_WRN

            # Rear Camera
            #if self.rcam_state != HX.CAM_STATE_ERR:
                #if self.rcam.poll() is not None:
                    #self.rcam_start()

                    #if self.rcam_state != HX.CAM_STATE_WRN:
                        #self.rcam_wrn_count += 1

                    #if self.rcam_wrn_count >= HX.CAM_MAX_WRN_COUNT:
                        #self.rcam_state = HX.CAM_STATE_WRN

            # Main Microphone
            if self.mmic_state != HX.CAM_STATE_ERR:
                if self.mmic.poll() is not None:
                    self.mmic_start()

                    if self.mmic_state != HX.CAM_STATE_WRN:
                        self.mmic_wrn_count += 1

                    if self.mmic_wrn_count >= HX.CAM_MAX_WRN_COUNT:
                        self.mmic_state = HX.CAM_STATE_WRN

            time.sleep(HX.CAM_DELAY)

            #if self.mcam_state == 1:
                ## VLC-1
                #r, w, e = select.select([self.mcam.stderr], [], [], 0.5)
                #if self.mcam.stderr in r:
                    #print("VLC-1 ERROR:")
                    #print(self.mcam.stderr.readline())

                #r, w, e = select.select([self.mcam.stdout], [], [], 0.5)
                #if self.mcam.stdout in r:
                    #print("VLC-1 OUT:")
                    #print(self.mcam.stdout.readline())

            #if self.rvid_state == 1:
                ## VLC-2
                #r, w, e = select.select([self.rvid.stderr], [], [], 0.5)
                #if self.rvid.stderr in r:
                    #print("RVID ERROR:")
                    #print(self.rvid.stderr.readline())

                #r, w, e = select.select([self.rcam.stderr], [], [], 0.5)
                #if self.rcam.stderr in r:
                    #print("VLC-2 ERROR:")
                    #print(self.rcam.stderr.readline())

                #r, w, e = select.select([self.rcam.stdout], [], [], 0.5)
                #if self.rcam.stdout in r:
                    #print("VLC-2 OUT:")
                    #print(self.rcam.stdout.readline())

            #if self.mmic_state == 1:
                ## VLC-3
                #r, w, e = select.select([self.mmic.stderr], [], [], 0)
                #if self.mmic.stderr in r:
                    #print("MMIC ERROR:")
                    #print(self.mmic.stderr.readline())

                #r, w, e = select.select([self.mmic.stdout], [], [], 0.5)
                #if self.mmic.stdout in r:
                    #print("MMIC OUT:")
                    #print(self.mmic.stdout.readline())


def main():
    HXcam = HXcamClass()
    HXcam.start()

    print("Execution started")

    command_view = '"Return" or CTRL+C to exit>'
    try:
        while True:
            command = input(command_view)

            if command == "":
                HXcam.stop()
                sys.exit()

    except KeyboardInterrupt:
        print("Terminate...")
        HXcam.stop()


if __name__ == '__main__':
    main()