/*
==================================================================================
  Copyright (c) 2019 AT&T Intellectual Property.
  Copyright (c) 2019 Nokia

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================================
*/

package control

import (
	"fmt"
	"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
	"sync"
)

type TransactionKey struct {
	SubID     uint16 // subscription id / sequence number
	TransType Action // action ongoing (CREATE/DELETE etc)
}

type TransactionXappKey struct {
	RmrEndpoint
	Xid string // xapp xid in req
}

type Transaction struct {
	tracker           *Tracker           // tracker instance
	Key               TransactionKey     // action key
	Xappkey           TransactionXappKey // transaction key
	OrigParams        *xapp.RMRParams    // request orginal params
	RespReceived      bool
	ForwardRespToXapp bool
}

func (t *Transaction) SubRouteInfo() SubRouteInfo {
	return SubRouteInfo{t.Key.TransType, t.Xappkey.RmrEndpoint.Addr, t.Xappkey.RmrEndpoint.Port, t.Key.SubID}
}

/*
Implements a record of ongoing transactions and helper functions to CRUD the records.
*/
type Tracker struct {
	transactionTable     map[TransactionKey]*Transaction
	transactionXappTable map[TransactionXappKey]*Transaction
	mutex                sync.Mutex
}

func (t *Tracker) Init() {
	t.transactionTable = make(map[TransactionKey]*Transaction)
	t.transactionXappTable = make(map[TransactionXappKey]*Transaction)
}

/*
Checks if a tranascation with similar type has been ongoing. If not then creates one.
Returns error if there is similar transatcion ongoing.
*/
func (t *Tracker) TrackTransaction(subID uint16, act Action, addr string, port uint16, params *xapp.RMRParams, respReceived bool, forwardRespToXapp bool) (*Transaction, error) {
	key := TransactionKey{subID, act}
	endpoint := RmrEndpoint{addr, port}
	xappkey := TransactionXappKey{endpoint, params.Xid}
	trans := &Transaction{t, key, xappkey, params, respReceived, forwardRespToXapp}
	t.mutex.Lock()
	defer t.mutex.Unlock()
	if _, ok := t.transactionTable[key]; ok {
		// TODO: Implement merge related check here. If the key is same but the value is different.
		err := fmt.Errorf("transaction tracker: Similar transaction with sub id %d and type %s is ongoing", key.SubID, key.TransType)
		return nil, err
	}
	if _, ok := t.transactionXappTable[xappkey]; ok {
		// TODO: Implement merge related check here. If the key is same but the value is different.
		err := fmt.Errorf("transaction tracker: Similar transaction with xapp key %v is ongoing", xappkey)
		return nil, err
	}
	t.transactionTable[key] = trans
	t.transactionXappTable[xappkey] = trans
	return trans, nil
}

/*
Retreives the transaction table entry for the given request. Controls that only one response is sent to xapp.
Returns error in case the transaction cannot be found.
*/
func (t *Tracker) RetriveTransaction(subID uint16, act Action) (*Transaction, error) {
	key := TransactionKey{subID, act}
	t.mutex.Lock()
	defer t.mutex.Unlock()
	if trans, ok := t.transactionTable[key]; ok {
		return trans, nil
	}
	err := fmt.Errorf("transaction record for Subscription ID %d and action %s does not exist", subID, act)
	return nil, err
}

/*
Deletes the transaction table entry for the given request and returns the deleted xapp's address and port for reference.
Returns error in case the transaction cannot be found.
*/
func (t *Tracker) completeTransaction(subID uint16, act Action) (*Transaction, error) {
	key := TransactionKey{subID, act}
	t.mutex.Lock()
	defer t.mutex.Unlock()
	if trans, ok1 := t.transactionTable[key]; ok1 {
		if _, ok2 := t.transactionXappTable[trans.Xappkey]; ok2 {
			delete(t.transactionXappTable, trans.Xappkey)
		}
		delete(t.transactionTable, key)
		return trans, nil
	}
	err := fmt.Errorf("transaction record for Subscription ID %d and action %s does not exist", subID, act)
	return nil, err
}

/*
Makes possible to to detect has response already received from BTS
Returns error in case the transaction cannot be found.
*/
func (t *Tracker) CheckResponseReceived(subID uint16, act Action) (*Transaction, bool, error) {
	key := TransactionKey{subID, act}
	t.mutex.Lock()
	defer t.mutex.Unlock()
	if trans, ok := t.transactionTable[key]; ok {
		if trans.RespReceived == false {
			trans.RespReceived = true
			// This is used to control that only one response action (success response, failure or timer) is excecuted for the transaction
			return trans, false, nil
		}
		return trans, true, nil
	}
	err := fmt.Errorf("transaction record for Subscription ID %d and action %s does not exist", subID, act)
	return nil, false, err
}

/*
Makes possible to receive response to retransmitted request to BTS
Returns error in case the transaction cannot be found.
*/
func (t *Tracker) RetryTransaction(subID uint16, act Action) error {
	key := TransactionKey{subID, act}
	t.mutex.Lock()
	defer t.mutex.Unlock()
	if trans, ok := t.transactionTable[key]; ok {
		trans.RespReceived = false
		return nil
	}
	err := fmt.Errorf("transaction record for Subscription ID %d and action %s does not exist", subID, act)
	return err
}
