// 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 vsync

import (
	"fmt"

	"v.io/v23/context"
	"v.io/v23/options"
	"v.io/v23/rpc"
	"v.io/v23/verror"
	"v.io/x/lib/vlog"
	"v.io/x/ref/services/syncbase/server/interfaces"
	"v.io/x/ref/services/syncbase/vclock"
)

// GetTime implements the responder side of the GetTime RPC.
// Important: This method wraps all errors in ErrGetTimeFailed so that
// runRemoteOp can reliably distinguish RPC errors from application errors. See
// TODO in runRemoteOp.
// TODO(sadovsky): This method does zero authorization, which means any client
// can send a syncgroup these requests. This seems undesirable.
func (s *syncService) GetTime(ctx *context.T, call rpc.ServerCall, req interfaces.TimeReq, initiator string) (interfaces.TimeResp, error) {
	vlog.VI(2).Infof("sync: GetTime: begin: from initiator %s", initiator)
	defer vlog.VI(2).Infof("sync: GetTime: end: from initiator %s", initiator)

	// For detecting sysclock changes that would break the NTP send/recv time
	// calculations. See detailed comment in vclock/ntp.go.
	recvNow, recvElapsedTime, err := s.vclock.SysClockVals()
	if err != nil {
		vlog.Errorf("sync: GetTime: SysClockVals failed: %v", err)
		return interfaces.TimeResp{}, verror.New(interfaces.ErrGetTimeFailed, ctx, err)
	}

	// Fetch local vclock data.
	data := &vclock.VClockData{}
	if err := s.vclock.GetVClockData(data); err != nil {
		vlog.Errorf("sync: GetTime: error fetching VClockData: %v", err)
		return interfaces.TimeResp{}, verror.New(interfaces.ErrGetTimeFailed, ctx, err)
	}

	// Check for sysclock changes.
	sendNow, _, err := s.vclock.SysClockValsIfNotChanged(recvNow, recvElapsedTime)
	if err != nil {
		vlog.Errorf("sync: GetTime: SysClockValsIfNotChanged failed: %v", err)
		return interfaces.TimeResp{}, verror.New(interfaces.ErrGetTimeFailed, ctx, err)
	}

	return interfaces.TimeResp{
		OrigTs:     req.SendTs,
		RecvTs:     s.vclock.ApplySkew(recvNow, data),
		SendTs:     s.vclock.ApplySkew(sendNow, data),
		LastNtpTs:  data.LastNtpTs,
		NumReboots: data.NumReboots,
		NumHops:    data.NumHops,
	}, nil
}

// syncVClock syncs the local Syncbase vclock with peer's Syncbase vclock.
// Works by treating the peer as an NTP server, obtaining a single sample, and
// then updating the local VClockData as appropriate.
func (s *syncService) syncVClock(ctx *context.T, peer connInfo) error {
	vlog.VI(2).Infof("sync: syncVClock: begin: contacting peer %v", peer)
	defer vlog.VI(2).Infof("sync: syncVClock: end: contacting peer %v", peer)

	// For detecting sysclock changes that would break the NTP send/recv time
	// calculations. See detailed comment in vclock/ntp.go.
	origNow, origElapsedTime, err := s.vclock.SysClockVals()
	if err != nil {
		vlog.Errorf("sync: syncVClock: SysClockVals failed: %v", err)
		return err
	}

	// TODO(sadovsky): Propagate the returned connInfo back to syncer so that we
	// leverage what we learned here about available mount tables and endpoints
	// when we continue on to the next initiation phase.
	var timeRespInt interface{}
	if _, timeRespInt, err = runAtPeer(ctx, peer, func(ctx *context.T, peer string) (interface{}, error) {
		return interfaces.SyncClient(peer).GetTime(ctx, interfaces.TimeReq{SendTs: origNow}, s.name, options.ConnectionTimeout(syncConnectionTimeout))
	}); err != nil {
		vlog.Errorf("sync: syncVClock: GetTime failed: %v", err)
		return err
	}

	// Check for sysclock changes.
	recvNow, _, err := s.vclock.SysClockValsIfNotChanged(origNow, origElapsedTime)
	if err != nil {
		vlog.Errorf("sync: syncVClock: SysClockValsIfNotChanged failed: %v", err)
		return err
	}

	timeResp, ok := timeRespInt.(interfaces.TimeResp)
	if !ok {
		err := fmt.Errorf("sync: syncVClock: unexpected GetTime response type: %#v", timeRespInt)
		vlog.Fatal(err)
		return err
	}

	return s.vclock.UpdateVClockData(func(data *vclock.VClockData) (*vclock.VClockData, error) {
		psd := &vclock.PeerSyncData{
			MySendTs:   s.vclock.ApplySkew(origNow, data),
			RecvTs:     timeResp.RecvTs,
			SendTs:     timeResp.SendTs,
			MyRecvTs:   s.vclock.ApplySkew(recvNow, data),
			LastNtpTs:  timeResp.LastNtpTs,
			NumReboots: timeResp.NumReboots,
			NumHops:    timeResp.NumHops,
		}
		if newData, err := vclock.MaybeUpdateFromPeerData(s.vclock, data, psd); err != nil {
			if _, ok := err.(*vclock.NoUpdateErr); ok {
				// Note, we still return an error in this case so that UpdateVClockData
				// does not even attempt to write VClockData back to the store.
				vlog.VI(2).Infof("sync: syncVClock: decided not to update VClockData: %v", err)
			} else {
				vlog.Errorf("sync: syncVClock: error updating VClockData: %v", err)
			}
			return nil, err
		} else {
			// Check again for sysclock changes after reading VClockData and calling
			// MaybeUpdateFromPeerData. VClockData is influenced by the system clock
			// via VClockD, and MaybeUpdateFromPeerData consults the system clock.
			if _, _, err := s.vclock.SysClockValsIfNotChanged(origNow, origElapsedTime); err != nil {
				vlog.Errorf("sync: syncVClock: SysClockValsIfNotChanged failed: %v", err)
				return nil, err
			} else {
				return newData, nil
			}
		}
	})
}
