// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package clock

import (
	"math"
	"time"

	"v.io/x/lib/vlog"
	"v.io/x/ref/services/syncbase/server/util"
	"v.io/x/ref/services/syncbase/store"
)

// ProcessPeerClockData accepts PeerSyncData and local ClockData and updates
// local ClockData and persists it if peer's clock is more accurate. Peer's
// clock is more accurate if all of the following conditions are met:
// 1) diff between the two clocks is > 2 seconds (avoids constant tweaking).
// 2) peer synced with NTP and it was more recent than local.
// 3) peer has not rebooted since NTP or the peer has rebooted since NTP but
//    the difference btw the two clocks is < 1 minute.
// 4) num hops for peer's NTP sync data is < 2, i.e. either the peer has
//    synced with NTP itself or it synced with another peer that did NTP.
func (c *VClock) ProcessPeerClockData(tx store.Transaction, resp *PeerSyncData, localData *ClockData) error {
	offset := (resp.RecvTs.Sub(resp.MySendTs) + resp.SendTs.Sub(resp.MyRecvTs)) / 2
	vlog.VI(2).Infof("clock: ProcessPeerClockData: offset between two clocks: %v", offset)
	if math.Abs(float64(offset.Nanoseconds())) <= util.PeerSyncDiffThreshold {
		vlog.VI(2).Info("clock: ProcessPeerClockData: the two clocks are synced within PeerSyncDiffThreshold.")
		return nil
	}
	if resp.LastNtpTs == nil {
		vlog.VI(2).Info("clock: ProcessPeerClockData: peer clock has not synced to NTP. Ignoring peer's clock.")
		return nil
	}
	if (localData != nil) && !isPeerNtpSyncMoreRecent(localData.LastNtpTs, resp.LastNtpTs) {
		vlog.VI(2).Info("clock: ProcessPeerClockData: peer NTP sync is less recent than local.")
		return nil
	}
	if isOverRebootTolerance(offset, resp.NumReboots) {
		vlog.VI(2).Info("clock: ProcessPeerClockData: peer clock is over reboot tolerance.")
		return nil
	}
	if resp.NumHops >= util.HopTolerance {
		vlog.VI(2).Info("clock: ProcessPeerClockData: peer clock is over hop tolerance.")
		return nil
	}
	vlog.VI(2).Info("clock: ProcessPeerClockData: peer's clock is more accurate than local clock. Syncing to peer's clock.")
	c.updateClockData(tx, resp, offset, localData)
	return nil
}

func (c *VClock) updateClockData(tx store.Transaction, peerResp *PeerSyncData, offset time.Duration, localData *ClockData) {
	systemTime := c.SysClock.Now()
	elapsedTime, err := c.SysClock.ElapsedTime()
	if err != nil {
		vlog.Errorf("clock: ProcessPeerClockData: error while fetching elapsed time: %v", err)
		return
	}
	systemTimeAtBoot := systemTime.Add(-elapsedTime)
	var skew time.Duration
	if localData == nil {
		// localData nil means that the local estimated UTC time is equal to
		// the system time. Hence the offset was in reality between the local
		// system clock and the remote estimated UTC time.
		skew = offset
	} else {
		skew = time.Duration(localData.Skew) + offset
	}

	newClockData := &ClockData{
		SystemTimeAtBoot:     systemTimeAtBoot.UnixNano(),
		Skew:                 skew.Nanoseconds(),
		ElapsedTimeSinceBoot: elapsedTime.Nanoseconds(),
		LastNtpTs:            peerResp.LastNtpTs,
		NumReboots:           peerResp.NumReboots,
		NumHops:              (peerResp.NumHops + 1),
	}
	if err := c.SetClockData(tx, newClockData); err != nil {
		vlog.Errorf("clock: ProcessPeerClockData: error while setting new clock data: %v", err)
	}
}

func isPeerNtpSyncMoreRecent(localNtpTs, peerNtpTs *time.Time) bool {
	if localNtpTs == nil {
		return true
	}
	if peerNtpTs == nil {
		return false
	}
	return peerNtpTs.After(*localNtpTs)
}

func isOverRebootTolerance(offset time.Duration, numReboots uint16) bool {
	return (math.Abs(float64(offset.Nanoseconds())) > util.RebootTolerance) && (numReboots > 0)
}
