func (chordNode *ChordNode) checkPredecessor() {

	chordNode.Logger.Println("Chord : In checkPredecessor")

	//RPC call to check predecessor
	jsonMessage := "{\"method\":\"CheckPredecessor\",\"params\":[]}"

	chordNode.Logger.Println("Predecessor:", chordNode.Predecessor)
	chordNode.Logger.Println("Predecessor serverInfo:", chordNode.FtServerMapping[chordNode.Predecessor])
	clientServerInfo := rpcclient.ServerInfo{}
	clientServerInfo.ServerID = chordNode.FtServerMapping[chordNode.Predecessor].ServerID
	clientServerInfo.Protocol = chordNode.FtServerMapping[chordNode.Predecessor].Protocol
	clientServerInfo.IpAddress = chordNode.FtServerMapping[chordNode.Predecessor].IpAddress
	clientServerInfo.Port = chordNode.FtServerMapping[chordNode.Predecessor].Port

	chordNode.Logger.Println("RPC call to:", clientServerInfo)

	client := &rpcclient.RPCClient{}
	err, response := client.RpcCall(clientServerInfo, jsonMessage)

	chordNode.Logger.Println("Response:", response)

	if err != nil {
		chordNode.Logger.Println(err)
		return
	}

	chordNode.Logger.Println("response.Result=", response.(*(rpcclient.ResponseParameters)).Result)
	// Set the predecessor to nil if empty response
	if response.(*(rpcclient.ResponseParameters)).Result == nil {
		chordNode.Logger.Println("SETTING PREDECESSOR TO NIL")
		chordNode.SetPredecessor(true, 0)
	}
}
// initially FingerTableIndex = 0
func (chordNode *ChordNode) fixFingers(FingerTableIndex int) {

	chordNode.Logger.Println("Chord : In fixFingers")

	//find the successor of (p+2^(i-1)) by initiaing the find_successor call from the current node
	nextNodeId := chordNode.Id + uint32(math.Pow(2, float64(FingerTableIndex-1)))
	jsonMessage := "{\"method\":\"findSuccessor\",\"params\":[" + fmt.Sprint(nextNodeId) + "]}"

	clientServerInfo := rpcclient.ServerInfo{}
	clientServerInfo.ServerID = chordNode.MyServerInfo.ServerID
	clientServerInfo.Protocol = chordNode.MyServerInfo.Protocol
	clientServerInfo.IpAddress = chordNode.MyServerInfo.IpAddress
	clientServerInfo.Port = chordNode.MyServerInfo.Port

	client := &rpcclient.RPCClient{}
	err, response := client.RpcCall(clientServerInfo, jsonMessage)

	if err != nil {
		chordNode.Logger.Println(err)
		return
	}

	// process only if response is present
	if response.(*(rpcclient.ResponseParameters)).Result != nil {
		chordNode.FingerTable[FingerTableIndex] = uint32((response.(*(rpcclient.ResponseParameters)).Result[0]).(float64))

		resultServerInfo := rpcclient.ServerInfo{}
		for key, value := range response.(*(rpcclient.ResponseParameters)).Result[1].(map[string]interface{}) {
			switch key {
			case "serverID":
				resultServerInfo.ServerID = value.(string)
				break
			case "protocol":
				resultServerInfo.Protocol = value.(string)
				break
			case "IpAddress":
				resultServerInfo.IpAddress = value.(string)
				break
			case "Port":
				resultServerInfo.Port = int(value.(float64))
			}
		}
		chordNode.FtServerMapping[chordNode.FingerTable[FingerTableIndex]] = resultServerInfo
		chordNode.Successor = chordNode.FingerTable[1]
	}
	chordNode.Logger.Println("FingerTable=", chordNode.FingerTable)
}
func getDefaultServerInfo() rpcclient.ServerInfo {
	serverInfo := rpcclient.ServerInfo{}
	serverInfo.ServerID = "mainserver"
	serverInfo.Protocol = "tcp"
	serverInfo.IpAddress = "127.0.0.1"
	serverInfo.Port = 1234

	return serverInfo
}
func (chordNode *ChordNode) join(serverInfo rpcclient.ServerInfo) {

	chordNode.Logger.Println("Chord : In Join")
	jsonMessage := "{\"method\":\"findSuccessor\",\"params\":[" + fmt.Sprint(chordNode.Id) + "]}"

	clientServerInfo := rpcclient.ServerInfo{}
	clientServerInfo.ServerID = serverInfo.ServerID
	clientServerInfo.Protocol = serverInfo.Protocol
	clientServerInfo.IpAddress = serverInfo.IpAddress
	clientServerInfo.Port = serverInfo.Port

	client := &rpcclient.RPCClient{}
	err, response := client.RpcCall(clientServerInfo, jsonMessage)

	if err != nil {
		chordNode.Logger.Println(err)
		return
	}

	chordNode.Predecessor = 0
	chordNode.Successor = uint32((response.(*(rpcclient.ResponseParameters)).Result[0]).(float64))

	resultServerInfo := rpcclient.ServerInfo{}
	for key, value := range response.(*(rpcclient.ResponseParameters)).Result[1].(map[string]interface{}) {
		switch key {
		case "serverID":
			resultServerInfo.ServerID = value.(string)
			break
		case "protocol":
			resultServerInfo.Protocol = value.(string)
			break
		case "IpAddress":
			resultServerInfo.IpAddress = value.(string)
			break
		case "Port":
			resultServerInfo.Port = int(value.(float64))
		}
	}
	chordNode.FtServerMapping[chordNode.Successor] = resultServerInfo
}
func (chordNode *ChordNode) updateFtServerMapping(id uint32, serverInfo rpcclient.ServerInfo) {

	if _, ok := chordNode.FtServerMapping[id]; !ok {

		clientServerInfo := rpcclient.ServerInfo{}
		clientServerInfo.ServerID = serverInfo.ServerID
		clientServerInfo.Protocol = serverInfo.Protocol
		clientServerInfo.IpAddress = serverInfo.IpAddress
		clientServerInfo.Port = serverInfo.Port

		chordNode.FtServerMapping[id] = clientServerInfo
	}
}
/*
Use this function to create server info to whom RPCcall is going to be made
Input: Chord Id of the server
*/
func (chordNode *ChordNode) PrepareClientServerInfo(chordID uint32) (rpcclient.ServerInfo, error) {
	clientServerInfo := rpcclient.ServerInfo{}
	if _, ok := chordNode.FtServerMapping[chordID]; ok {
		clientServerInfo.ServerID = chordNode.FtServerMapping[chordID].ServerID
		clientServerInfo.Protocol = chordNode.FtServerMapping[chordID].Protocol
		clientServerInfo.IpAddress = chordNode.FtServerMapping[chordID].IpAddress
		clientServerInfo.Port = chordNode.FtServerMapping[chordID].Port
		return clientServerInfo, nil
	} else {
		customError := errors.New("Entry not found in FTServerMapping")
		chordNode.Logger.Println(customError)
		return rpcclient.ServerInfo{}, customError
	}

}
/*
request <-"{"method":"Notify","params":[10,{"ServerID":"9999","Protocol":"tcp","IpAddress":"127.0.0.1","Port":1235}]}"
response <- "{"result":[],"id":,"error":null }"
*/
func (rpcMethod *RPCMethod) Notify(jsonInput RequestParameters, jsonOutput *ResponseParameters) error {

	//Initialize rpcserver
	var err error
	err, rpcMethod.rpcServer = GetRPCServerInstance()
	var customError error
	if err != nil {
		customError = errors.New("Getting Server Instance error :" + err.Error())
		rpcMethod.rpcServer.logger.Println(customError)
		return customError
	}

	rpcMethod.rpcServer.logger.Println("RPCCall: In Notify")
	rpcMethod.rpcServer.logger.Println("Input=", jsonInput)

	var probablePredecessorId uint32
	probablePredecessorServerInfo := rpcclient.ServerInfo{}
	var parameters []interface{}
	parameters = jsonInput.Params

	//get inputId from the []interface
	for k, v := range parameters {
		if k == 0 {
			probablePredecessorId = uint32(v.(float64))
		} else if k == 1 {
			resultServerInfo := rpcclient.ServerInfo{}
			for key, value := range v.(map[string]interface{}) {
				switch key {
				case "serverID":
					resultServerInfo.ServerID = value.(string)
					break
				case "protocol":
					resultServerInfo.Protocol = value.(string)
					break
				case "IpAddress":
					resultServerInfo.IpAddress = value.(string)
					break
				case "Port":
					resultServerInfo.Port = int(value.(float64))
				}
			}
			probablePredecessorServerInfo = resultServerInfo
		}
	}

	//probablePredecessor ∈ (predecessor, chordNode)
	isPredecessorNil, predecessor := rpcMethod.rpcServer.chordNode.GetPredecessor()
	//predecessor == chordNode.Id refers to the case where the ActualNodesInRing = 1 i.e. predecessor is the node itself
	nodeId := rpcMethod.rpcServer.chordNode.Id
	if isPredecessorNil ||
		(probablePredecessorId > predecessor && probablePredecessorId < nodeId) ||
		predecessor == nodeId ||
		(probablePredecessorId < nodeId && predecessor > probablePredecessorId && predecessor > nodeId) ||
		(probablePredecessorId > nodeId && predecessor < probablePredecessorId && predecessor > nodeId) {

		rpcMethod.rpcServer.chordNode.SetPredecessor(false, probablePredecessorId)
		rpcMethod.rpcServer.chordNode.FtServerMapping[rpcMethod.rpcServer.chordNode.Predecessor] = probablePredecessorServerInfo

		//transfer keys to predecessor whose hash is less than predecessor chord ID
		rpcMethod.rpcServer.transferKeysToPredecessor()
	}

	return nil
}
func (rpcMethod *RPCMethod) FindSuccessor(jsonInput RequestParameters, jsonOutput *ResponseParameters) error {

	//Initialize rpcserver
	var err error
	err, rpcMethod.rpcServer = GetRPCServerInstance()
	var customError error
	if err != nil {
		customError = errors.New("Getting Server Instance error :" + err.Error())
		rpcMethod.rpcServer.logger.Println(customError)
		return customError
	}

	rpcMethod.rpcServer.logger.Println("RPCCall: In FindSuccessor ")
	rpcMethod.rpcServer.logger.Println("Input=", jsonInput)
	defer rpcMethod.rpcServer.logger.Println("Exited FindSuccssor=")

	var inputId uint32
	var succId uint32
	var interId uint32

	succServerInfo := rpcclient.ServerInfo{}

	var parameters []interface{}
	parameters = jsonInput.Params

	//get inputId from the []interface
	for k, v := range parameters {
		if k == 0 {
			inputId = uint32(v.(float64))
		}
	}

	/*
	   if (id ∈ (n, successor])
	      return successor;
	*/
	rpcMethod.rpcServer.logger.Println("Find Successor of (id)" + fmt.Sprint(inputId))
	rpcMethod.rpcServer.logger.Println("Current Node (n):" + fmt.Sprint(rpcMethod.rpcServer.chordNode.Id))
	rpcMethod.rpcServer.logger.Println("Current Node Successor (successor):" + fmt.Sprint(rpcMethod.rpcServer.chordNode.Successor))

	//case when only 1 node in chord ring - that node will be the successor
	if rpcMethod.rpcServer.chordNode.Id == rpcMethod.rpcServer.chordNode.Successor {
		succId = rpcMethod.rpcServer.chordNode.Id

		//basic condition
	} else if rpcMethod.rpcServer.chordNode.Id < inputId && inputId <= rpcMethod.rpcServer.chordNode.Successor {
		succId = rpcMethod.rpcServer.chordNode.Successor

		//successor id is less than node id - check whether inputId falls between (n,sucessor + 2^m)

	} else if rpcMethod.rpcServer.chordNode.Successor < rpcMethod.rpcServer.chordNode.Id && (inputId > rpcMethod.rpcServer.chordNode.Id || inputId < rpcMethod.rpcServer.chordNode.Successor) {
		succId = rpcMethod.rpcServer.chordNode.Successor

	} else {
		interId = rpcMethod.rpcServer.chordNode.ClosestPrecedingNode(inputId)

		// if call is being forwarded to the current node itself, that means current node itself is the successor
		if interId == rpcMethod.rpcServer.chordNode.Id {
			succId = rpcMethod.rpcServer.chordNode.Id
		} else {

			//create rpc call "{"method":"findSuccessor","params":[inputId]}"
			jsonMessage := "{\"method\":\"findSuccessor\",\"params\":[" + fmt.Sprint(inputId) + "]}"

			clientServerInfo := rpcclient.ServerInfo{}
			clientServerInfo.ServerID = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].ServerID
			clientServerInfo.Protocol = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].Protocol
			clientServerInfo.IpAddress = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].IpAddress
			clientServerInfo.Port = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].Port

			client := &rpcclient.RPCClient{}
			err, response := client.RpcCall(clientServerInfo, jsonMessage)

			if err != nil {
				fmt.Println(err)
				return nil
			}

			jsonOutput.Result = make([]interface{}, 2)
			// process only if response is present
			if response.(*(rpcclient.ResponseParameters)).Result != nil {
				succId = uint32(response.(*(rpcclient.ResponseParameters)).Result[0].(float64))

				resultServerInfo := rpcclient.ServerInfo{}
				for key, value := range response.(*(rpcclient.ResponseParameters)).Result[1].(map[string]interface{}) {
					switch key {
					case "serverID":
						resultServerInfo.ServerID = value.(string)
						break
					case "protocol":
						resultServerInfo.Protocol = value.(string)
						break
					case "IpAddress":
						resultServerInfo.IpAddress = value.(string)
						break
					case "Port":
						resultServerInfo.Port = int(value.(float64))
					}
				}
				succServerInfo = resultServerInfo

				//insert successor ID into jsonOutput
				jsonOutput.Result[0] = succId

				//insert succId's serverInfo into jsonOutput
				jsonOutput.Result[1] = succServerInfo
			}
			rpcMethod.rpcServer.logger.Println("Result from findSucc=", jsonOutput.Result)
			return nil
		} // END-ELSE
	}

	jsonOutput.Result = make([]interface{}, 2)
	//insert successor ID into jsonOutput
	jsonOutput.Result[0] = succId

	//insert succId's serverInfo into jsonOutput
	if rpcMethod.rpcServer.chordNode.Id == succId {
		jsonOutput.Result[1] = rpcMethod.rpcServer.chordNode.MyServerInfo
	} else {
		jsonOutput.Result[1] = rpcMethod.rpcServer.chordNode.FtServerMapping[succId]
	}
	return nil
}
func (chordNode *ChordNode) stabilize() {
	chordNode.Logger.Println("Chord : In Stabilize")

	//RPC call to get predecessor of successor
	jsonMessage := "{\"method\":\"GetPredecessor\",\"params\":[]}"

	clientServerInfo := rpcclient.ServerInfo{}
	clientServerInfo.ServerID = chordNode.FtServerMapping[chordNode.FingerTable[1]].ServerID
	clientServerInfo.Protocol = chordNode.FtServerMapping[chordNode.FingerTable[1]].Protocol
	clientServerInfo.IpAddress = chordNode.FtServerMapping[chordNode.FingerTable[1]].IpAddress
	clientServerInfo.Port = chordNode.FtServerMapping[chordNode.FingerTable[1]].Port

	client := &rpcclient.RPCClient{}
	err, response := client.RpcCall(clientServerInfo, jsonMessage)

	if err != nil {
		chordNode.Logger.Println(err)
		return
	}

	// process only if response is present -- CASE WHERE SUCCESSOR LEAVES ABRUPTLY
	if response.(*(rpcclient.ResponseParameters)).Result != nil {
		isPredecessorOfSuccessorNil := (response.(*(rpcclient.ResponseParameters)).Result[0]).(bool)
		predecessorOfSuccessor := uint32((response.(*(rpcclient.ResponseParameters)).Result[1]).(float64))

		resultServerInfo := rpcclient.ServerInfo{}
		for key, value := range response.(*(rpcclient.ResponseParameters)).Result[2].(map[string]interface{}) {
			switch key {
			case "serverID":
				resultServerInfo.ServerID = value.(string)
				break
			case "protocol":
				resultServerInfo.Protocol = value.(string)
				break
			case "IpAddress":
				resultServerInfo.IpAddress = value.(string)
				break
			case "Port":
				resultServerInfo.Port = int(value.(float64))
			}
		}
		predecessorOfSuccessorServerInfo := resultServerInfo

		//update the successor
		if !isPredecessorOfSuccessorNil {
			isPredecessorNil, _ := chordNode.GetPredecessor()
			//predecessor == chordNode.Id refers to the case where the ActualNodesInRing = 1 i.e. predecessor is the node itself
			if (predecessorOfSuccessor > chordNode.Id && predecessorOfSuccessor < chordNode.Successor) ||
				(!isPredecessorNil && chordNode.Successor == chordNode.Id) ||
				(chordNode.Successor < chordNode.Id && predecessorOfSuccessor < chordNode.Successor) ||
				(chordNode.Successor < chordNode.Id && predecessorOfSuccessor > chordNode.Successor && predecessorOfSuccessor > chordNode.Id) {
				chordNode.Successor = predecessorOfSuccessor
				chordNode.FtServerMapping[chordNode.Successor] = predecessorOfSuccessorServerInfo
			}
		}
	}

	chordNode.Logger.Println("About to make RPC call: Notify")
	//RPC call to notify the successor about the predecessor(i.e. current node)
	jsonMessage = "{\"method\":\"Notify\",\"params\":[" + fmt.Sprint(chordNode.Id) + ", {\"serverID\":\"" + chordNode.MyServerInfo.ServerID + "\", \"protocol\":\"" + chordNode.MyServerInfo.Protocol + "\",\"IpAddress\":\"" + chordNode.MyServerInfo.IpAddress + "\",\"Port\":" + fmt.Sprint(chordNode.MyServerInfo.Port) + "}]}"

	clientServerInfo = rpcclient.ServerInfo{}
	clientServerInfo.ServerID = chordNode.FtServerMapping[chordNode.FingerTable[1]].ServerID
	clientServerInfo.Protocol = chordNode.FtServerMapping[chordNode.FingerTable[1]].Protocol
	clientServerInfo.IpAddress = chordNode.FtServerMapping[chordNode.FingerTable[1]].IpAddress
	clientServerInfo.Port = chordNode.FtServerMapping[chordNode.FingerTable[1]].Port

	client = &rpcclient.RPCClient{}
	err, _ = client.RpcCall(clientServerInfo, jsonMessage)

	if err != nil {
		chordNode.Logger.Println(err)
		return
	}
}