import sys
import pandas as pd
import time
import numpy as np
import math

# Argument Check
# Read the command line arguments
if len(sys.argv) != 5:
    print ("\nError! Wrong number of parameters")
    print ("5 parameters are required")
    print ("Usages: python topsis.py <InputDataFile> <Weights> <Impacts> <ResultFileName>")
    print ("Example: python topsis.py inputfile.csv “1,1,1,2” “+,+,-,+” result.csv")
    sys.exit(0)
    
    
# Variables are defined        
# Command Line Arguments
        
args = len(sys.argv) - 1
inputFile = sys.argv[1]
outputFile = sys.argv[4]

try:
    weights = list(map(float ,sys.argv[2].split(',')))
    impacts = list(map(str ,sys.argv[3].split(','))) 
except:
    print('Weights or Impacts are not provided in proper format ')
    sys.exit(0)
        
for each in impacts :
    if each not in ('+','-'):
        print('Impacts are not provided in proper format ')
        sys.exit(0)

try:
    input_data = pd.read_csv(inputFile)
    
except:
    print(file+' File not found');
    sys.exit(0)
        
if len(list(input_data.columns))<=2:
    print('Input file should contain 3 or more columns '+ file)
    sys.exit()



# Input File are read through read_csv() functions
inputTable = pd.read_csv(inputFile)
weights = [int(i) for i in sys.argv[2].split(',')]
impacts = sys.argv[3].split(',')
labels = [i for i in inputTable[1:]]

# MAIN PROGRAM STARTS HERE

# Each file is manipulated
outputTable = inputTable.copy()

# Add the Topsis Score and Rank column to the output table
outputTable['Topsis Score'] = [0 for i in range(0,len(inputTable))]
outputTable['Rank'] = [0 for i in range(0,len(inputTable))]

sumOfSquares = {labels[i] : 0 for i in range(1,len(labels))}
newWeights = {labels[i] : 0 for i in range(1,len(labels))}

# Processing the input table
for index, row in inputTable.iterrows():
    for i in labels[1:]:
        sumOfSquares[i] += row[i]*row[i]

for i in sumOfSquares:
    sumOfSquares[i] = math.sqrt(sumOfSquares[i])
    
# Perform the TOPSIS Normalization operations on the data
inputTable = outputTable.copy()

for index, row in outputTable.iterrows():
    for i in labels[1:]:
        inputTable.loc[index,i] = row[i] / sumOfSquares[i]
        
# Define weights and impact dictionary      
newWeights = {i:weights[index]/sum(weights) for index,i in enumerate(labels[1:])}
newImpacts = {i:impacts[index] for index,i in enumerate(labels[1:])}


for index, row in outputTable.iterrows():
    for i in labels[1:]:
        inputTable.loc[index,i] *= newWeights[i]
        
v1 = dict()
v2 = dict()

for index, row in outputTable.iterrows():
    for i in labels[1:]:
        if newImpacts[i] == '+':
            v1[i] = max(inputTable[i])
            v2[i] = min(inputTable[i])
        elif newImpacts[i] == '-':
            v1[i] = min(inputTable[i])
            v2[i] = max(inputTable[i])
   
inputTable = inputTable.append(v1,ignore_index=True)
inputTable = inputTable.append(v2,ignore_index=True)     

inputTable['S1'] = [0 for i in range(0,len(inputTable))]
inputTable['S2'] = [0 for i in range(0,len(inputTable))]
inputTable['S12'] = [0 for i in range(0,len(inputTable))]

for index, row in inputTable.iterrows():
    if index < len(inputTable) - 2:
        for i in labels[1:]:
            row['S1'] += (float(inputTable.loc[len(inputTable)-2][i]) - float(row[i])) * (float(inputTable.loc[len(inputTable)-2][i]) - float(row[i])) 
            row['S2'] += (float(inputTable.loc[len(inputTable)-1][i]) - float(row[i])) * (float(inputTable.loc[len(inputTable)-1][i]) - float(row[i]))
        row['S1'] = math.sqrt(row['S1'])
        row['S2'] = math.sqrt(row['S2'])
        row['S12'] = row['S1'] + row['S2']
        outputTable.loc[index,'Topsis Score'] = row['S2'] / (row['S1'] + row['S2'])

rank_values = sorted(outputTable['Topsis Score'], reverse = True)


for index,row in inputTable.iterrows():
    if index < len(inputTable) - 2:
        outputTable.loc[index,'Rank'] = rank_values.index(outputTable.loc[index]['Topsis Score']) + 1
    

print('Result')
print(outputTable)
    
# Save DataFrame to csv File
current_time = time.localtime(time.time())
current_time = str(time.strftime("%Y%m%d", current_time))

outputTable.to_csv(outputFile + current_time+'.csv',index=False)
print('\nResult File successfully created')

        
        