import requests
import os
from inotify.adapters import InotifyTree
import inotify.constants as ic
import json
import re
from threading import Thread

class Watcher:

    def __init__(self, tracked_folder, include_regex, exclude_regex):
        self.tracked_folder = tracked_folder
        self.include_regex = include_regex
        self.exclude_regex = exclude_regex
        self.url = os.environ['API_URL']

    def add_file(self, path):
        folder, file = os.path.split(path)

        resp = requests.get('{}/titles/search'.format(self.url),
                            params={'path': path})

        if resp.status_code == 200:
            titles = json.loads(resp.text)
            for title in titles:

                if title['path'] == path:
                    # print('Already in system: {}'.format(path))
                    return

        resp = requests.post('{}/titles'.format(self.url),
                             json={'path': path})

        if resp.status_code == 201:
            print('Added: {}'.format(file))
        elif resp.status_code == 400:
            print('Not added: {}'.format(file))

    def watch_folder(self):

        print('Setting up watches for {}'.format(self.tracked_folder))
        i = InotifyTree(self.tracked_folder)
        print('Complete')

        for event in i.event_gen():

            if event is not None:

                (eventinfo, typenames, folder, file) = event

                print(event)

                if eventinfo.mask in [ic.IN_MOVED_TO, ic.IN_CLOSE_WRITE, ic.IN_CREATE]:

                    path = os.path.join(folder, file).encode('utf-8', 'surrogateescape').decode('utf-8')

                    if re.search(self.include_regex, path):

                        if not re.search(self.exclude_regex, path):

                            print('Adding file {}'.format(path))
                            self.add_file(path)
                            print('Complete')

if __name__ == "__main__":
    w1 = Watcher('/data/tvshows', r'\.mkv|\.mp4|\.ts\Z', r'\.grab')
    t1 = Thread(target=w1.watch_folder)
    t1.start()

    w2 = Watcher('/data/movies', r'\.mkv|\.mp4|\.ts\Z', r'\.grab')
    t2 = Thread(target=w2.watch_folder)
    t2.start()

    t1.join()
    t2.join()


import socket
import pickle
import numpy as np
import cv2
from cv2 import aruco

#-----------------------------------------------------------------------------------
# SETUP SOCKETS

# CAMERA CLIENT - SERVER SOCKET
TCP_IP_ADDRESS = "127.0.0.1"                                # LAN IP ADDRESS OF SERVER
TCP_PORT_NO = 20375
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind(('', TCP_PORT_NO))
serversocket.listen(5)
clientsocket, address = serversocket.accept()

# SERVER - UITY CLIENT SOCKET
UDP_IP_ADDRESS = "127.0.0.1"                                # LAN IP ADDRESS OF SERVER
UDP_PORT_NO = 52375
serversocket2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket2.bind(('', UDP_PORT_NO))
serversocket2.listen(5)
clientsocket2, address = serversocket2.accept()
clientsocket2.setblocking(False)

#-----------------------------------------------------------------------------------
# INITIALIZE / DECLARE GLOBAL VARIABLES

buf = []
bytesrecvd = 0

WIDTH = 640
HEIGHT = 480
DATALEN = WIDTH * HEIGHT
frame = 1

target = [0,1,2]

aruco_dict = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters =  aruco.DetectorParameters_create()

#-----------------------------------------------------------------------------------

def detectMarkers(image_array):
        corners, ids, rejectedImgPoints = aruco.detectMarkers(image_array, aruco_dict, parameters=parameters)
        if ids is None:
                combination_ids = [4]
        else:
                combination_ids = np.reshape(ids, ids.shape[0])
        combination_ids.sort()
        # combination_ids = np.array([0,1,2])
        if np.array_equal(combination_ids,target):
                print("YOU PICKED THE RIGHT PIECES.")
        else: print("KEEP TRYING.")
        gray = aruco.drawDetectedMarkers(imarr, corners)
        return combination_ids

#-----------------------------------------------------------------------------------

while True:
        data = clientsocket.recv(DATALEN)
        if not data: break
        bytesrecvd += len(data)
        buf.extend(data)

        if bytesrecvd >= DATALEN:
                # print("buffer complete!")
                flattened = buf[0:DATALEN]
                imarr = np.array(flattened, dtype=np.uint8)
                imarr = np.reshape(imarr, (HEIGHT, WIDTH))

                detected = detectMarkers(imarr)
                print(detected)
                cv2.imshow('local', imarr)
                cv2.waitKey(1)

                b_array = bytearray()
                size = len(detected)
                sbytes = size.to_bytes(2, 'little')
                b_array.append(sbytes[0])
                b_array.append(sbytes[1])
                for marker in detected:
                        b_array.append(marker)
                try:
                        clientsocket2.send(b_array)
                except:
                        print("client closed")

                buf = []                # CLEAR BUFFER
                bytesrecvd = 0          # RESET BYTES RECEIVED COUNTER

#-----------------------------------------------------------------------------------


"""
The below program gets data from excel sheet and the look up for the data on a website and then scraps that data
and then insert it on a excel sheet.
"""
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import openpyxl as op
from selenium import webdriver

drive = "" #! Please enter drive path.
fileName = "" #! Please enter file name.
path = drive + fileName

r = 3 #! Please change the row number to the row number from which you would like to start reading the file.
nameSet = set()
def institutionNames():
    """
    This function load all the data from a excel sheet for a particular column and stores it in a list named "nameList".
    Current design to get data from single column but can be chaged to get data from multiple column.
    """
    itn = op.load_workbook(path)
    itnsh = itn["Sheet1"]
    maxRow = 1500 # itnsh.max_row
    for s in range(r, (maxRow + 5)):
        name = itnsh.cell(row = s, column = 3).value #! Please change the column number based on the column number in your file.
        if name != None:
            name = name.strip()
            nameSet.add(name)
    itn.close()
    # print(nameSet)
    return nameSet

appByDict1 = dict()
affByDict1 = dict()
appByDict2 = dict()
affByDict2 = dict()
def dataScreapping():
    """
    This function will scrap the data from the website and store it a dict name "accreditationsDict".
    It uses selenium webdriver for searching and getting the data.
    """
    chromeDriverPath = "" #! Please add your googlechrome driver path.
    chromeOptions = webdriver.ChromeOptions()
    #? Feel free to adjust the below argument based on your requirement.
    chromeOptions.add_argument("start-maximized")
    chromeOptions.add_argument("disable-infobars")
    chromeOptions.add_argument("disable-notifications")
    chromeOptions.add_argument("disable-popup-blocking")
    # chromeOptions.add_argument("headless")
    chromeOptions.add_experimental_option("detach", True)

    driver = webdriver.Chrome(chromeDriverPath, options=chromeOptions)
    driver.get("https://www.getmyuni.com/")

    #? Getting the below data from the above function. So please call the above function before calling this function.
    nameSetLength = len(nameSet)
    print(nameSetLength)
    curr = 0
    for i in nameSet:
        curr += 1
        print(f"{curr} - {i}")
        driver.get("https://www.getmyuni.com/")

        # time.sleep(1)
        searchBarID = "coll-name-box"
        WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.ID, searchBarID)))
        searchBar = driver.find_element_by_id(searchBarID)
        searchBar.send_keys(i)

        try:
            # time.sleep(5)
            #! In the below line change div[8] to div[7], if the function returns "Institution not found" consistantly.
            #! It may be because of div position has changed.
            #? Please choose one of the below versions of Xpath.
            searchedNameXpath = "/html/body/div[7]/section/div[2]/div[2]/div[4]/a"
            # searchedNameXpath ="//*[@id='search-div']/section/div[2]/div[2]/div[4]/a[1]"
            WebDriverWait(driver, 8).until(EC.element_to_be_clickable((By.XPATH, searchedNameXpath)))
            searchedName = driver.find_element_by_xpath(searchedNameXpath)
            searchedName.click()

            time.sleep(2)
            #? Getting data from the first element.
            try:
                affEle1Xpath = "/html/body/div[5]/div[1]/div/div/div/div/div/div/div[2]/div[1]/div/strong[1]"
                affEle1 = driver.find_element_by_xpath(affEle1Xpath)
                affEleText1 = affEle1.text
                # print(affEleText1)

                if affEleText1 == "Approved By:":
                    appBy = driver.find_element_by_xpath("/html/body/div[5]/div[1]/div/div/div/div/div/div/div[2]/div[1]/div/span")
                    appByText = appBy.text
                    appByDict1[i] = appByText
                elif affEleText1 == "Affiliated By:":
                    affBy = driver.find_element_by_xpath("/html/body/div[5]/div[1]/div/div/div/div/div/div/div[2]/div[1]/div/a")
                    affByText = affBy.text
                    affByDict1[i] = affByText
                else:
                    print("First data unavailable.")
            except:
                pass

            #? Getting data from the second element.
            try:
                affEle2 = driver.find_element_by_xpath("/html/body/div[5]/div[1]/div/div/div/div/div/div/div[2]/div[1]/div/strong[2]")
                affEleText2 = affEle2.text

                if affEleText2 == "Approved By:":
                    appBy = driver.find_element_by_xpath("/html/body/div[5]/div[1]/div/div/div/div/div/div/div[2]/div[1]/div/span")
                    appByText = appBy.text
                    appByDict2[i] = appByText
                elif affEleText2 == "Affiliated By:":
                    affBy = driver.find_element_by_xpath("/html/body/div[5]/div[1]/div/div/div/div/div/div/div[2]/div[1]/div/a")
                    affByText = affBy.text
                    affByDict2[i] = affByText
                else:
                    pass
            except:
                print("Second data not available.")
        except:
            print("Institution not found!!!")
    return appByDict1, affByDict1, appByDict2, affByDict2,

def dataPosting():
    """
    This functions open the same excel sheet from which we retrieve data
    and then will store the collected data in the new column.
    """
    itn = op.load_workbook(path)
    itnSh = itn["Sheet1"]
    maxRow = itnSh.max_row
    for s in range(r, (maxRow + 10)):
        name = itnSh.cell(row = s, column = 3).value
        for key, val in appByDict1.items():
            if key == name:
                approvedBy1 = itnSh.cell(row = s, column = 11)
                approvedBy1.value = val
        for key, val in affByDict1.items():
            if key == name:
                affiliatedBy1 = itnSh.cell(row = s, column = 12)
                affiliatedBy1.value = val
        for key, val in appByDict2.items():
            if key == name:
                approvedBy2 = itnSh.cell(row = s, column = 11)
                approvedBy2.value = val
        for key, val in affByDict2.items():
            if key == name:
                affiliatedBy2 = itnSh.cell(row = s, column = 12)
                affiliatedBy2.value = val
    itn.save(path)
    itn.close()
    print("All Done!!!")

#? Calling the above functions, which will get data from excel, search it on a website and stored the collected data in same excel sheet.
institutionNames()
dataScreapping()
# print(appByDict1)
# print(affByDict1)
# print(appByDict2)
# print(affByDict2)
dataPosting()


import urllib
try:
    from urllib.request import urlopen
except ImportError:
    from urllib import urlopen

import shutil
import os
import json

def download_package_json(package_name):
    url = "https://pypi.org/pypi/{package_name}/json".format(package_name=package_name)
    try:
        response = urlopen(url)
        return json.loads(response.read().decode())
    except urllib.error.HTTPError as e:
        if e.code == 404:
            raise ValueError('package "{package_name}" does not exist on pypi'.format(package_name=package_name))
        else:
            raise ValueError(
                'error fetching pypi package "{package_name}" information'.format(package_name=package_name)
            )

def download_package(url, directory):
    base_filename = os.path.join(directory, os.path.basename(url))

    with urlopen(url) as response:
        with open(base_filename, "wb") as f:
            f.write(response.read())

    previous_directory_state = set(os.listdir(directory))
    shutil.unpack_archive(base_filename, directory)
    current_directory_state = set(os.listdir(directory))

    changed_filenames = current_directory_state - previous_directory_state
    if len(changed_filenames) > 1:
        raise ValueError(
            "expected that extracting sdist archive only produces one directory: {changed_filenames}".format(changed_filenames=changed_filenames)
        )

    return list(changed_filenames)[0]


#! /usr/bin/env python3

from gpiozero import LED
from gpiozero import Button
from time import sleep

print("Start control.py")

# LED1 - Pin18   GPIO24
# LED2 - Pin16   GPIO23
# LED3 - Pin8    GPIO14
# LED4 - Input power

# BUTTON1 - Pin12  GPIO18 -> PIN26 GPIO7
# BUTTON2 - Pin10  GPIO15
# BUTTON3 - Power

# Rotary encoder
# ENC1     - Pin22  GPIO25
# ENC2     - Pin24  GPIO8

class RadioIface:

    def __init__(self):
        self.led_1 = LED("GPIO24")
        self.led_2 = LED("GPIO23")
        self.led_3 = LED("GPIO14")
        self.button_1 = Button("GPIO7")
        self.button_2 = Button("GPIO15")
        self.enc_1 = Button("GPIO25")
        self.enc_2 = Button("GPIO08")

    def all_leds_on(self):
        self.led_1.on()
        self.led_2.on()
        self.led_3.on()
        return

    def all_leds_off(self):
        self.led_1.off()
        self.led_2.off()
        self.led_3.off()
        return

    def print_buttons(self):
        # print("-------------------------------------------------")
        print("b1={} b2={} enc1={} enc2={}".format(self.button_1.is_pressed, self.button_2.is_pressed,
                                                   self.enc_1.is_pressed, self.enc_2.is_pressed))

    def print_encoder(self):
        sym_d = {True: "+", False: "|"}
        print("{}     {}".format(sym_d[self.enc_1.is_pressed], sym_d[self.enc_2.is_pressed]))
        return

radio_iface = RadioIface()

print("enc1    enc2")
while True:
    # radio_iface.all_leds_on()
    # sleep(1)
    # radio_iface.all_leds_off()
    # sleep(1)

    # radio_iface.print_buttons()

    radio_iface.print_encoder()

    sleep(1)


import pytest

from datetime import datetime, timedelta

from xbox.webapi.authentication.token import Token, AccessToken, RefreshToken, XSTSToken, UserToken

def test_token_validity(jwt):
    time_now = datetime.utcnow()
    time_minus_1day = time_now - timedelta(days=1)
    time_minus_14days = time_now - timedelta(days=14)
    time_plus_14days = time_now + timedelta(days=14)

    token_invalid = Token(jwt, time_minus_14days, time_minus_1day)
    token_valid = Token(jwt, time_now, time_plus_14days)

    assert token_invalid.is_valid is False
    assert token_valid.is_valid is True

    assert token_valid.date_issued == time_now
    assert token_valid.date_valid == time_plus_14days

def test_access_refresh_token_validity(jwt):
    access_token_invalid = AccessToken(jwt, 0)
    access_token_120seconds = AccessToken(jwt, 120)
    refresh_token_14days = RefreshToken(jwt)

    assert access_token_invalid.is_valid is False
    assert access_token_120seconds.is_valid is True
    assert refresh_token_14days.is_valid is True
    assert access_token_invalid.jwt == jwt

def test_token_string_conversion(jwt, token_timestring, token_datetime):
    token_datestring = Token(jwt, token_timestring, token_timestring)

    assert token_datestring.date_issued == token_datetime

def test_token_from_dict(jwt, token_timestring, token_datetime):
    token_dict = UserToken(jwt, token_timestring, token_timestring).to_dict()

    token = Token.from_dict(token_dict)

    # Invalid Name
    token_dict['name'] = 'InvalidTokenName'
    with pytest.raises(ValueError):
        Token.from_dict(token_dict)

    assert token.jwt == jwt
    assert token.date_valid == token_datetime

def test_token_to_dict(jwt, token_timestring, token_datetime):
    token_dict = XSTSToken(jwt, token_timestring, token_timestring).to_dict()

    assert token_dict['name'] == 'XSTSToken'
    assert token_dict['jwt'] == jwt
    assert token_dict['date_valid'] == token_timestring
    assert token_dict['date_issued'] == token_timestring


# -*- coding: utf-8 -*-:
import json
from common.util.util import CommonUtil
from common.util.logger import Logger

class ActiveTask(object):
    def __init__(self, mr_task=None):
        self.logger = Logger(self.__class__.__name__).get()
        if mr_task:
            self.id = mr_task.id
            self.name = mr_task.name
            self.information = mr_task.information
            self.bin_file_uri = mr_task.bin_file_uri
            self.has_derivative_table = mr_task.has_derivative_table
            self.type = mr_task.type
            self.export_dir_uri = mr_task.export_dir_uri
            self.priority = mr_task.priority
            self.table_stage_list = mr_task.table_stage_list
            self.triggle_cond_list = mr_task.triggle_cond_list
            self.export_table_list = mr_task.export_table_list
            self.schedule_cron = mr_task.task_schedule
            self.hive_params_list = mr_task.hive_params_list
            self.create_time = mr_task.create_time
            self.begin_time = None
            self.end_time = None
            #self.db_name = mr_task.db_name
        else:
            self.id = None
            self.name = None
            self.information = None
            self.bin_file_uri = None
            self.has_derivative_table = None
            self.type = None
            self.export_dir_uri = None
            self.priority = None
            self.table_stage_list = None
            self.triggle_cond_list = None
            self.export_table_list = None
            self.schedule_cron = None
            self.hive_params_list = None
            self.create_time = None
            self.begin_time = None
            self.end_time = None
            #self.db_name = None

    def __eq__(self, other):
        return self.id == other.id and \
                self.name == other.name and \
                self.information == other.information and \
                self.bin_file_uri == other.bin_file_uri and \
                self.type == other.type

    def __hash__(self):
        return hash((self.id, self.name, self.information, self.bin_file_uri, self.type))

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        ret_str = "{ActiveTask(id=%s, name=%s, information=%s, bin_file_uri=%s, has_derivative_table=%s, type=%s, export_dir_uri=%s, table_stage_list=[" % \
                  (self.id, self.name, self.information, self.bin_file_uri, self.has_derivative_table, self.type, self.export_dir_uri)
        for table_stage in self.table_stage_list:
            ret_str += str(table_stage)
            ret_str += ","
        ret_str += "]}"
        return ret_str

    def should_process(self):
        if self.type < 2:
            return True
        cur_datetime = CommonUtil.getCurrentDatetime()
        cur_year = cur_datetime.year
        cur_day_in_week = cur_datetime.weekday()
        cur_month = cur_datetime.month
        cur_day_in_month = cur_datetime.day
        cur_hour = cur_datetime.hour
        cur_minute = cur_datetime.minute
        self.logger.debug("task schedule_cron is: %s, current time is:{minutes(%s), hour(%s),"
                        " day_in_month(%s), month(%s), day_in_week(%s)}" % \
                        (self.schedule_cron, cur_minute, cur_hour, cur_day_in_month, cur_month, cur_day_in_week))
        if cur_year in self.schedule_cron.years and \
            cur_day_in_week in self.schedule_cron.days_in_week and \
            cur_month in self.schedule_cron.months and \
            cur_day_in_month in self.schedule_cron.days_in_month and \
            cur_hour in self.schedule_cron.hours and \
            cur_minute in self.schedule_cron.minutes:
            return True
        return False

    def get_stage_info(self):
        return CommonUtil.encodeTableStage(self.table_stage_list)