/*
 * Copyright 2018-present Open Networking Foundation

 * 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 model

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/opencord/voltha-go/common/log"
	"reflect"
)

// DataRevision stores the data associated to a revision along with its calculated checksum hash value
type DataRevision struct {
	Data interface{}
	Hash string
}

// NewDataRevision creates a new instance of a DataRevision structure
func NewDataRevision(root *root, data interface{}) *DataRevision {
	dr := DataRevision{}
	dr.Data = data
	dr.Hash = dr.hashData(root, data)

	return &dr
}

func (dr *DataRevision) hashData(root *root, data interface{}) string {
	var buffer bytes.Buffer

	if IsProtoMessage(data) {
		if pbdata, err := proto.Marshal(data.(proto.Message)); err != nil {
			log.Debugf("problem to marshal protobuf data --> err: %s", err.Error())
		} else {
			buffer.Write(pbdata)
			// To ensure uniqueness in case data is nil, also include data type
			buffer.Write([]byte(reflect.TypeOf(data).String()))
		}

	} else if reflect.ValueOf(data).IsValid() {
		dataObj := reflect.New(reflect.TypeOf(data).Elem())
		if json, err := json.Marshal(dataObj.Interface()); err != nil {
			log.Debugf("problem to marshal data --> err: %s", err.Error())
		} else {
			buffer.Write(json)
		}
	} else {
		dataObj := reflect.New(reflect.TypeOf(data).Elem())
		buffer.Write(dataObj.Bytes())
	}

	// Add the root pointer that owns the current data for extra uniqueness
	rootPtr := fmt.Sprintf("%p", root)
	buffer.Write([]byte(rootPtr))

	return fmt.Sprintf("%x", md5.Sum(buffer.Bytes()))[:12]
}
