import os, sys
import pandas as pd
import numpy as np
import sklearn as sk
from sklearn import preprocessing
import math
'''
coordsi.py is a module for convert coordinates to SI unit.

Warning: This module convert coordinates with heuristic method.
This moudle will be deprecated
'''

def readCam (filepath):
    '''
    Create a dataframe from cam*.csv file.
    You must specify camera id. default is 1.
    '''
    try:
        df = pd.read_csv(filepath, header=0, dtype={'x': np.float64, 'y': np.float64, 'z': np.float64, 'frame': np.int64})
        return df
    except Exception as e:
        print(e)

def summaryOriginCoord (root, camid=0):
    '''
    Show brief information of listed surgeon coordinate.
    '''
    d = root
    try:
        if camid == 1 or camid == 2 :
            df = pd.DataFrame(columns=['approx_total_frame', 'x_min', 'x_max', 'y_min', 'y_max', 'z_min', 'z_max'])
            subdirs = [x[0] for x in os.walk(d)]
            for d in subdirs[1:]:
                row = []
                #get a list of files in directory
                files = os.listdir(d)
                count_svo = len([s for s in files if "_1.csv" in s])
                filpath = os.path.join(d,'cam'+str(camid)+'.csv')
                if os.path.isfile(filpath):
                    arr = readCam(os.path.join(d,'cam'+str(camid)+'.csv'))
                    row = [3600 *count_svo, arr['x'].min(), arr['x'].max(), arr['y'].min(), arr['y'].max(), arr['z'].min(), arr['z'].max()]
                    df.loc[d] = row
                else:
                    print('Warning: '+filpath+' is not exist.')
                    continue
            return df
        else:
            print("Error: Camera ID must be 1 or 2. type camid=1 or camid=2 after dirpath")
    except Exception as e:
        print(e)

    


def convertToSI (origin, w, l, h):
    '''
    Waring: This function will be deprecated!
    Convert coordinates to SI unit with w, l, h.
    w, l, h are heuristic value. It will be changed after calibration and each surgeon room will geat unique value.
    '''
    try:
        df = origin.copy()
        #normailze dataframe[0] from -1 to 1
        df['x'] = preprocessing.minmax_scale(df['x'], feature_range=(-(w/2), (w/2)), axis=0, copy=True)
        #normailze dataframe[1] from -0.75 to 0.75
        df['y'] = preprocessing.minmax_scale(df['y'], feature_range=(-(l/2), (l/2)), axis=0, copy=True)
        #subtract dataframe[z] from int(4) and normailze from 0.93m to 1.8m (0 as floor)
        df['z'] = h - df['z']
        df['z'] = preprocessing.minmax_scale(df['z'], feature_range=(0.93,1.8), axis=0, copy=True)
        #change column order x, y to y, x
        df = df[['y', 'x', 'z', 'frame']]
        #change column name y to X, x to Y
        df = df.rename(columns={'y': 'x', 'x': 'y'})
        return df
    except Exception as e:
        print(e)

def getVelocity (dataframe):
    try:
        df  = dataframe
        df['positionvectorvalue'] = (df['x']**2 + df['y']**2 + df['z']**2)
        buffer1, buffer2 = df['positionvectorvalue'].copy(), df['positionvectorvalue'].copy()
        buffer1, buffer2 = buffer1.to_frame(), buffer2.to_frame()
        buffer1, buffer2 = list(buffer1.loc[:, 'positionvectorvalue']), list(buffer2.loc[:, 'positionvectorvalue'])
        buffer3 = [0.0]
        for x in range(0, len(buffer2)-1):
            buffer3.append(buffer2[x])
        buffer3  = np.array(buffer1) - np.array(buffer3)
        for x in range(0, len(buffer3)):
            buffer3[x] = math.sqrt(abs(buffer3[x]))
        buffer3[0] = 0.0
        df['velocity'] = buffer3
        return df
    except Exception as e:
        print(e)

def getAcceleration (dataframe):
    try:
        df = dataframe
        buffer1, buffer2 = df['velocity'].copy(), df['velocity'].copy()
        buffer1, buffer2 = buffer1.to_frame(), buffer2.to_frame()
        buffer1, buffer2 = list(buffer1.loc[:, 'velocity']), list(buffer2.loc[:, 'velocity'])
        buffer3 = [0.0]
        for x in range(0, len(buffer2)-1):
            buffer3.append(buffer2[x])
        buffer3  = np.array(buffer1) - np.array(buffer3)
        buffer3[1] = 0.0
        df['acceleration'] = buffer3
        return df
    except Exception as e:
        print(e)

def getFullTrace (dataframe, approx_total_frame):
    try:
        df = dataframe
        total_frame = int(approx_total_frame)
        handletrace = pd.DataFrame(columns=['x', 'y', 'z', 'frame', 'positionvectorvalue', 'velocity', 'acceleration', 'isValid'])
        handletrace = pd.concat([handletrace, pd.DataFrame(np.zeros((total_frame,8)), columns=['x', 'y', 'z', 'frame', 'positionvectorvalue','velocity', 'acceleration', 'isValid'])], axis=0)
        for x in range(0, len(df)):
            handletrace.loc[df.loc[x, 'frame']] = df.loc[x]
        handletrace['isValid'] = handletrace['isValid'].fillna(0)
        return handletrace
    except Exception as e:
        print(e)

def addValidDetection (dataframe, threshold = 25.0):
    '''
    threshold value is suitable for only 1st surgeon room(Seoul 801).
    We can make threshold in every surgeon room by using epipolar geometry.(but needs more cameras with different positions)
    '''
    try:
        df = dataframe
        top = threshold
        bottom = -threshold
        for x in range(0, len(df)):
            if bottom < df['acceleration'][x] < top:
                df['isValid'][x] = 1
            else:
                df['isValid'][x] = 0
        return df
    except Exception as e:
        print(e)        
