#!/usr/bin/python3
#import cProfile
#import re
import  requests 
from datetime import datetime
#import calendar
import os
from html import unescape
import urllib.parse
#import time
import curses
import sqlite3 as lite
import youtube
#import os.path
#import math
from curses.textpad import Textbox, rectangle
#527 biale z podkreśleniem 520 szare z podkresleniem
#https://www.googleapis.com/youtube/v3/search?key=AIzaSyBwecAq2aCjRxStpOclQZNSRpJEI2HtvX0&part=snippet&type=channel&q=etho&maxResults=10

def get_video_id(url):
    url_data = urllib.parse.urlparse(url)
    query = urllib.parse.parse_qs(url_data.query)
    return query['v'][0]


def get_valid_filename(string):
    return "".join([c for c in string if c.isalpha() or c.isdigit() or c == ' ']).rstrip().replace(' ', '_')

def file_exists(video_title):
    return os.path.isfile("/public/youtube/" + get_valid_filename(video_title)+".mp4")



class Mc(object):
    youtube_info_url = 'http://youtube.com/get_video_info?video_id='
    youtube_channels = []
    youtube_api_key = "AIzaSyBwecAq2aCjRxStpOclQZNSRpJEI2HtvX0"
    videos = {}
    timestamp = 0
    longest_nick = 0
    selected_video = 0
    connection = lite.connect('/public/python/test.db')
    offset = 0
    channel_id_filter = 0
    total_videos = 0
    search = ''


    def __init__(self):
        self.read_data()
        self.total_videos = self.get_total_videos()
        
    def read_data(self):
        with self.connection:
            cur = self.connection.cursor()
            cur.execute('SELECT id, nick, uploadsid FROM channel')
            self.youtube_channels = cur.fetchall()
            if self.channel_id_filter > 0:
                cur.execute("SELECT nick, title, videoid, channel_id, seen FROM video JOIN channel ON  video.channel_id = channel.id WHERE deleted IS NULL AND channel.id = ? AND title LIKE ?  ORDER BY publishtime DESC LIMIT ?, 30", (self.channel_id_filter, '%'+self.search+'%', self.offset))
            else:
                cur.execute("SELECT nick, title, videoid, channel_id, seen FROM video JOIN channel ON  video.channel_id = channel.id WHERE deleted IS NULL  AND title LIKE ? ORDER BY publishtime DESC LIMIT ?, 30", ('%'+self.search+'%', self.offset))
               
            self.videos = cur.fetchall()
            

    def lite(self, channels):
        with self.connection:
            cur = self.connection.cursor()
            for channel in channels:
                cur.execute("SELECT * FROM channel WHERE nick = :nick", {"nick": channel['nick']})
                self.connection.commit()
                row = cur.fetchone()
                if row == None:
                    cur.execute(
                        "INSERT INTO channel('playlist', 'nick', 'channel', 'userid', 'uploadsid') VALUES (?, ?, ?, ?, ?)",
                        ('1', channel['nick'], channel['channel'], channel['userid'], channel['uploadsid']))
            self.connection.commit()

    def get_video_info_url(self, video_id):
        return self.youtube_info_url + video_id

    def print_videos(self, stdscr):
        iterator = 0 
        for video in self.videos:		
            is_file = "X" if file_exists(video[1]) else " "	
            if iterator == self.selected_video:
                stdscr.addstr(iterator, 0, "[%s] %s %-60s" % (video[0].ljust(14, ' '), is_file, video[1]), curses.A_STANDOUT)
            elif video[4] == 1:
                stdscr.addstr(iterator, 0, "[%s] %s %-60s" % (video[0].ljust(14, ' '), is_file, video[1]), curses.color_pair(236))
                #stdscr.addstr(iterator, 0, "[%s] %s %s %-60s" % (video[0].ljust(14, ' '), is_file, video[1], iterator+self.offset),  curses.color_pair(iterator+self.offset))

            else:
                #stdscr.addstr(iterator, 0, "[%s] %s %s %-60s" % (video[0].ljust(14, ' '), is_file, video[1], iterator+self.offset),  curses.color_pair(iterator+self.offset))
                stdscr.addstr(iterator, 0, "[%s] %s %-60s" % (video[0].ljust(14, ' '), is_file, video[1]),  curses.color_pair(255))
            iterator += 1

    def print_botom_info(self, stdscr):
        pages = int(self.total_videos) // 30
        stdscr.addstr(len(self.videos), 0, "Play [Enter] | Download [D] | Refresh [R] | Exit [Q] |", curses.A_BOLD )
        if_search = curses.color_pair(90) if len(self.search) > 0 else curses.A_BOLD
        if_filter = curses.color_pair(90) if self.channel_id_filter > 0 else curses.A_BOLD
        stdscr.addstr(len(self.videos), 55, "Search [S]", if_search)
        stdscr.addstr(len(self.videos), 65, " | ", curses.A_BOLD)
        stdscr.addstr(len(self.videos), 68, "Filter [F]" , if_filter)
        stdscr.addstr(len(self.videos), 78, " | " , curses.A_BOLD)
        stdscr.addstr(len(self.videos), 81, "[<-/->] | [%d / %d] " % (self.offset /30+1,  pages), curses.A_BOLD)
    
    def get_total_videos(self):
        with self.connection:
            cur = self.connection.cursor()
            if self.channel_id_filter > 0:
                 cur.execute("SELECT count(video.id) FROM video JOIN channel ON video.channel_id = channel.id AND  channel.id = ? WHERE title like ?", (self.channel_id_filter, '%'+self.search+'%'))
            else:
                 cur.execute("SELECT count(video.id) FROM video JOIN channel ON  video.channel_id = channel.id WHERE title LIKE ?", ('%'+self.search+'%',))
            return int(cur.fetchone()[0])

    def get_video_direct_urls(self, video_id):
        streams = []
        data = requests.get(self.get_video_info_url(video_id))
        unescaped = unescape(data.text)
        decoded = urllib.parse.parse_qs(data.text)

        for stream in decoded['url_encoded_fmt_stream_map'][0].split(','):
            streams.append(urllib.parse.parse_qs(stream))

        return streams

    def get_all_videos(self):
        for id, channelName, uploadListId in self.youtube_channels:
            
            videos = youtube.playlistItems(uploadListId, self.youtube_api_key, True)
            for row in videos:
                self.save_video(id, row)


    def get_recent_videos_silent(self, allVideos=False):
         for id, channelName, uploadListId in self.youtube_channels:
            videos = youtube.playlistItems(uploadListId, self.youtube_api_key, allVideos)
            for row in videos:
                self.save_video(id, row)

   
			

    def get_recent_videos(self, stdscr):
        channel_iterator = 1

        for id, channelName, uploadListId in self.youtube_channels:
            stdscr.addstr(channel_iterator, 0, '%s %d/%d' % (channelName,0,50))
            channel_iterator+=1    

        channel_iterator = 1
        for id, channelName, uploadListId in self.youtube_channels:
            videos = youtube.playlistItems(uploadListId, self.youtube_api_key)
            videos_iterator = 1
            for row in videos:
                self.save_video(id, row)
                stdscr.addstr(channel_iterator, 0, '%s %d/%d' % (channelName,videos_iterator,  len(videos)))
                stdscr.refresh()
                videos_iterator+=1
            channel_iterator+=1 



    def save_video(self, channel_id, video_row):
        with self.connection:
            cur = self.connection.cursor()
			
            cur.execute(
                    "INSERT OR IGNORE INTO video('channel_id', 'title', 'views', 'duration', 'videoid', 'publishtime') VALUES (?, ?, ?, ?, ?, ?)",
                    (channel_id, video_row['title'], 0, 0, video_row['videoid'], video_row['timestamp']))
            self.connection.commit()


    def main_loop(self, stdscr):
        stdscr.keypad(True)
        stdscr.clear()
	

        curses.use_default_colors()

        for i in range(0, curses.COLORS):
            curses.init_pair(i, i, -1);
			
        self.print_videos(stdscr)
        mc.print_botom_info(stdscr)
        curses.curs_set(0)

		
        while 1:
            stdscr.refresh()

            key = stdscr.getch()

            if key == curses.KEY_UP:
                stdscr.refresh()
                mc.selected_video -= 1
                if mc.selected_video < 0:
                    mc.selected_video = len(mc.videos) - 1
            elif key == curses.KEY_DOWN:
                stdscr.refresh()
                mc.selected_video += 1
                if mc.selected_video >= len(mc.videos):
                    mc.selected_video = 0
            elif key == curses.KEY_RIGHT:
                stdscr.clear()
                self.offset += 30;
                self.read_data()
                
            elif key == curses.KEY_LEFT:
                stdscr.clear()
                if(self.offset > 30):
                    self.offset -= 30
                else:
                    self.offset = 0
                self.read_data()
            elif key in [ord('F'), ord('f')]:
                stdscr.clear()
                if self.channel_id_filter > 0:
                    self.channel_id_filter = 0;
                else:
                    self.channel_id_filter = mc.videos[mc.selected_video][3]
                self.offset = 0
                self.read_data()
                self.total_videos = self.get_total_videos()

            elif key in [ord('A'), ord('a')]:
                stdscr.clear()
                editwin = curses.newwin(1, 49, 2, 1)
                stdscr.addstr(0,0,'Search channel:')
                stdscr.addstr(1, 0, '+-------------------------------------------------+')                
                stdscr.addstr(2, 0, '|                                                 |')                
                stdscr.addstr(3, 0, '+-------------------------------------------------+')                

                stdscr.refresh()
                box = Textbox(editwin)
                box.edit()

                self.searchChannel = box.gather()
                
                
                
                
            elif key in [ord('S'), ord('s')]:
                stdscr.clear()
                editwin = curses.newwin(1,49, 2,1)
                stdscr.addstr(0, 0, 'SEARCH BY TITLE:')                
                stdscr.addstr(1, 0, '+-------------------------------------------------+')                
                stdscr.addstr(2, 0, '|                                                 |')                
                stdscr.addstr(3, 0, '+-------------------------------------------------+')                


                stdscr.refresh()
                box = Textbox(editwin)
                box.edit()

                self.search = box.gather()
                self.read_data()
                self.total_videos = self.get_total_videos()

                stdscr.clear()

            
            elif key in [ord('R'), ord('r')]:
                stdscr.clear()

                stdscr.addstr(0, 0, 'REFRESHING LIST')
                stdscr.refresh()
                self.read_data()
                self.total_videos = self.get_total_videos()


            elif key in [ord('D'), ord('d')]:
                video_id = mc.videos[mc.selected_video][2]
                streams = mc.get_video_direct_urls(video_id)

                for stream in streams:
                    if stream['itag'][0] == "22":
                        os.system('wget -nv --show-progress -O "/public/youtube/%s.mp4"  "%s" >> /dev/null &' % (
                            get_valid_filename(mc.videos[mc.selected_video][1]), stream['url'][0]))

            elif key  in [ord('Q'), ord('q')]:  # esc
                curses.endwin()
                os._exit(0)
            elif key == 10 or key == curses.KEY_ENTER: 
                video_id = mc.videos[mc.selected_video][2]
                #stdscr.clear()
                #stdscr.addstr(0, 0,  '/public/youtube/' +  get_valid_filename(mc.videos[mc.selected_video][1])+".mp4")

               # stdscr.refresh()
               # time.sleep(4)

                with self.connection:
                    cur = self.connection.cursor()
                    cur.execute('UPDATE video SET seen = 1 WHERE videoid = ?', (video_id, ))
                    self.youtube_channels = cur.fetchall()
                    self.connection.commit()




                if file_exists(mc.videos[mc.selected_video][1]):

                #    stdscr.addstr(1, 1,  '/public/youtube/' +  get_valid_filename(mc.videos[mc.selected_video][1])+".mp4")
                 #   stdscr.refresh()
                    os.system('omxplayer -b  "%s"' %  ("/public/youtube/" +  get_valid_filename(mc.videos[mc.selected_video][1])+".mp4" ))
                else:
                    streams = mc.get_video_direct_urls(video_id)
				
                    for stream in streams:
                        # print (stream['itag'])
                        if stream['itag'][0] == "22":
                            os.system('omxplayer -b "%s"' % stream['url'][0])
                            stdscr.clear()

            mc.print_videos(stdscr)
            mc.print_botom_info(stdscr)


if __name__ == "__main__":
    mc = Mc()

#test('test')

#print (youtube.search('generikb', 'channel', "AIzaSyBwecAq2aCjRxStpOclQZNSRpJEI2HtvX0"))

#videos = youtube.playlistItems("UU-_VTaWqRsZ1nzZLHQIGwQA", "AIzaSyBwecAq2aCjRxStpOclQZNSRpJEI2HtvX0")
#print(videos)
#mc.get_all_videos()

#mc.lite(channels)

# print (mc.get_video_info_url('https://www.youtube.com/watch?v=vw61gCe2oqI'))

# mc.get_videos('UUFKDEp9si4RmHFWJW1vYsMA')

# mc.get_videos('UUJTWU5K7kl9EE109HBeoldA')
# os.system('clear')
#
    try:
        curses.wrapper(mc.main_loop)
        #cProfile.run('re.compile("foo|bar")')
    except KeyboardInterrupt:
        curses.endwin()
        os._exit(0)

