
import sys
import pandas as pd
from argparse import ArgumentParser
from pathlib import Path

n = len(sys.argv)
if n < 5:
    exit('Enter more arguments')
if n > 5:
    exit('Enter less arguments')


input = sys.argv[1]
df = pd.read_csv(input)
# df.shape

df.head()

if df.shape[1] < 3:
    print('Input file contains less than 3 columns hence exiting the code')
    exit()

# checking From 2nd to last columns must contain numeric values only i.e (Handling of non-numeric values)
dummy = df.select_dtypes(exclude=["float", 'int'])
dummy.shape
if dummy.shape[1] > 1:
    print("Non-numerical values found in between 2nd to last columns hence exiting the code")
    exit()

weight = sys.argv[2]
impacts = sys.argv[3]
Output_File_Name = sys.argv[4]

weight = weight.split(",")
impacts = impacts.split(",")

weights = []
for i in range(0, len(weight)):
    weights.append(int(weight[i]))


col_len = df.shape[1]-1
if len(weight) != col_len:
    print("Size of weight is not equal to the len of col therefore exiting the code")
    exit()
elif len(impacts) != col_len:
    print("Size of impacts is not equal to the len of col therefore exiting the code")
    exit()
elif len(impacts) != len(weight):
    print("Size of weights and size of impacts does not matches therefore existing the code")
    exit()

for i in range(0, len(impacts)):
    if impacts[i] != '+' and impacts[i] != '-':
        print("Impacts contains values other than '+' and '-' therefore existing the code")
        exit()

if len(weight) != col_len:
    print("Weight is not separated by ','")
    exit()
elif len(impacts) != col_len:
    print("Impacts is not separated by ',")
    exit()

df1 = df.copy()
# df1


def normalize(df1, nCol, weight):
    for i in range(1, nCol):
        temp = 0

        for j in range(len(df1)):
            temp = temp + df1.iloc[j, i]**2
        temp = temp**0.5

        for j in range(len(df1)):
            df1.iloc[j, i] = (df1.iloc[j, i] / temp)*weight[i-1]


normalize(df, df.shape[1], weights)

# df

df2 = df.copy()
ideal_best = (df2.max().values)[1:]
ideal_worst = (df2.min().values)[1:]

# ideal_best, ideal_worst


def idealValues(df2, nCol, ideal_best, ideal_worst, impact):
    for i in range(1, nCol):
        if impact[i-1] == '-':
            ideal_best[i-1], ideal_worst[i -
                                         1] = ideal_worst[i-1], ideal_best[i-1]
    return ideal_best, ideal_worst


ideal_best, ideal_worst = idealValues(
    df, df.shape[1], ideal_best, ideal_worst, impacts)

# print(ideal_best)
# print(ideal_worst)


def euc_and_performance_score(ideal_best, ideal_worst, df):
    topsis_score = []  # Topsis score
    ideal_best_dist = []  # distance positive
    ideal_worst_dist = []  # distance negative
    # Calculating distances and Topsis score for each row
    for i in range(len(df)):
        temp_p, temp_n = 0, 0
        for j in range(1, df.shape[1]):
            temp_p = temp_p + (ideal_best[j-1] - df.iloc[i, j])**2
            temp_n = temp_n + (ideal_worst[j-1] - df.iloc[i, j])**2
        temp_p, temp_n = temp_p**0.5, temp_n**0.5
        topsis_score.append(temp_n/(temp_p + temp_n))
        ideal_best_dist.append(temp_n)
        ideal_worst_dist.append(temp_p)
    return topsis_score, ideal_best_dist, ideal_worst_dist


topsis_score, ideal_best_dist, ideal_worst_dist = euc_and_performance_score(
    ideal_best, ideal_worst, df)

# topsis_score

df1['Topsis Score'] = topsis_score

# df1
result = df1.copy()

result['Rank'] = (result['Topsis Score'].rank(method='max', ascending=False))
result = result.astype({"Rank": int})

result.to_csv(Output_File_Name, index=False)

print(result)
