# *********************************
# Package for dmaatti.
# Contains constant variables, methods to be used and
# utility functions
# Matti Sarkela 1.2.2019
# *********************************

import json
import requests
import hmac
import hashlib
import base64
import time
from datetime import datetime
import sys

# These variables will not change


inventory = {"22": {"stock":"", "price":"1.00", "itemName":"purkka"}, 
             "50": {"stock":"", "price":"0.99", "itemName":"patukka"}, 
             "88": {"stock":"", "price":"1.50", "itemName":"merkki"}, 
             "99": {"stock":"", "price":"2.75", "itemName":"tasku-teppo"}}
             
logSeparator = " ------------------" #Used inside payment loop
logSeparator2 = " ******************" 

# The MerchantKey is currently calculated as the following, based on MerchantId provided by Danske Bank: 
# MerchantKey = SHA256(ISO-8859-1({Substring(MerchantId, 3, 6)})) The substring of the MerchantId 
# is calculated by skipping the first 3 characters and using the next 6 characters.
# Implementation guide page 30.

# Maybe not needed to read from file. Is it a problem if code can't save new one automatically?
try:
    with open('dmaattiData.txt', 'r') as f:
        lines = f.readlines()
    UniquePoSId = lines[0]
    UniquePoSId = UniquePoSId.replace("\r", "").replace("\n", "")
    # UniquePoSId = "36d784c1-37b8-4a2b-8ee5-31f3804fedd2"
    
except IOError:
    print("Error: File dmaattiData.txt does not appear to exist.")

#Is this needed at all?
def updateMethod_UniquePoSId(UniquePoSId):
    RegisterPoS["PoSId"] = UniquePoSId
    
def apiRequest(method, bodyContent):
    # This function sends data to endpoint
    # method = name of request
    # bodyContent = dict of body data

    unixdate = str(int(time.time())) #Convert float to int ant int to string
    request = json.dumps(bodyContent, separators=(',',':')) #Extra spaces must be taken out from JSON
    msgToCode = endpoint+method+" "+request+" "+unixdate
    
    # digest = hmac.new(ApiKey.encode('utf-8'), msgToCode, digestmod=hashlib.sha256).digest()
    digest = hmac.new(ApiKey.encode('utf-8'), msgToCode.encode('utf-8'), digestmod=hashlib.sha256).digest()
    signature = base64.b64encode(digest).decode() #encode('utf-8')
    auth = signature+" "+unixdate
    header = {'Content-Type':'application/json','Authorization':auth.encode('utf-8')}

    response = requests.post(endpoint+method, data=request, headers=header)

    print(response)
    json_data = json.loads(response.text)
    print(json_data)
    
    return response
    
def paymentStartHMAC():
    paymentKey = hashlib.sha256(MerchantKey.encode("latin_1")).digest() #required  iso8859-1 which is "West Europe"
    msgToCode = PaymentStart.get("MerchantId")+PaymentStart.get("LocationId")+"#"+PaymentStart.get("PoSId")+"#"+PaymentStart.get("OrderId")+"#"+PaymentStart.get("Amount")+"#"+PaymentStart.get("BulkRef")+"#"
    digest = hmac.new(paymentKey, msgToCode.encode('utf-8'), digestmod=hashlib.sha256).digest()
    signature = base64.b64encode(digest).decode()
    PaymentStart["HMAC"] = signature

def writeLog(logString, type=None, response=None):
    try:
        f =  open('log.txt', 'a')
        if ((response==None) and (type==None)):
            f.write(str(datetime.now())+logString+"\n")
        elif (response==None):
            f.write(str(datetime.now())+" "+type+": "+logString+"\n")
        else:
            f.write(str(datetime.now())+" "+type+": "+logString+" | Status code: "+str(response.status_code)+" | " + response.text+"\n")
        
        f.close()
    except IOError:
        print("Error: log.txt writing error.")

def readInventory():
    try:
        with open('inventory.txt') as f:  
            inventory = json.load(f)
        print("Inventory read succesfully!")
        writeLog("Invetory read from file succesfully.","OK")
    except IOError:
        print("Could not read inventory.txt!")
        writeLog("Could not read inventory.txt!","ERROR")
    
    return inventory
    
def writeInventory(inventory):
    try:
        # with open('inventory.txt', 'w') as f:  
            # json.dump(inventory, f)
        with open('inventory.txt', 'w', encoding='utf8') as json_file:
            json.dump(inventory, json_file, ensure_ascii=False)
        print("Inventory was updated succesfully!")
        writeLog("Invetory was updated succesfully.","OK")
    except IOError:
        print("Could not update inventory.txt!")
        writeLog("Could not update inventory.txt!","ERROR")
        
#Base of all requests:
RegisterPoS = {
"MerchantId":MerchantId, 
"LocationId":LocationId, 
"PoSId":UniquePoSId, 
"Name":"Dmaatti" 
} 
UnRegisterPoS = {
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId
} 
AssignPoSUnitIdToPos = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId,
"PoSUnitId":PoSUnitId 
} 
UnAssignPoSUnitIdToPoS = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId,
"PoSUnitId":PoSUnitId  
} 
ReadPoSAssignPoSUnitId = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId,
} 
ReadPoSUnitAssignedPoSId = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSUnitId":PoSUnitId 
}
GetUniquePoSId ={"MerchantId":MerchantId}
GetCurrentPayment = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId,
} 
GetPosList = {
"MerchantId":MerchantId, 
"LocationId":LocationId 
}
# GetLocationList
PaymentStart = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId,
"OrderId":"", 
"Amount":"", 
"BulkRef":"", # Check, no BulkPost agreement? 
"Action":"Start", #Check if we have to support "Update"
"CustomerTokenCalc":"1", #We donät have loyality program
"HMAC":"" 
} 
GetPaymentStatus = {
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId,
"OrderId":"" 
} 
PaymentCancel = { 
"MerchantId":MerchantId,
"LocationId":LocationId,
"PoSId":UniquePoSId
}
# PaymentRefund
# Reservation methods not used
