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

import (
	"fmt"
	"reflect"
	"sort"
	"time"

	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/vdl"
	"v.io/v23/verror"
	"v.io/x/js.core/test_service"
)

const pkgPath = "release/javascript/core/test_service/test_serviced"

var errIndexOutOfBounds = verror.Register(pkgPath+".errIndexOutOfBounds", verror.NoRetry, "{1:}{2:} Page index out of bounds{:_}")

// A simple in-memory implementation of a Cache service.
type cacheImpl struct {
	cache          map[string]*vdl.Value
	mostRecent     test_service.KeyValuePair
	lastUpdateTime time.Time
}

// NewCached returns a new implementation of CacheServerMethods.
func NewCached() test_service.CacheServerMethods {
	return &cacheImpl{cache: make(map[string]*vdl.Value)}
}

// Set sets a value for a key.  This should never return an error.
func (c *cacheImpl) Set(_ *context.T, _ rpc.ServerCall, key string, value *vdl.Value) error {
	c.cache[key] = value
	c.mostRecent = test_service.KeyValuePair{Key: key, Value: value}
	c.lastUpdateTime = time.Now()
	return nil
}

// Get returns the value for a key.  If the key is not in the map, it returns
// an error.
func (c *cacheImpl) Get(ctx *context.T, _ rpc.ServerCall, key string) (*vdl.Value, error) {
	if value, ok := c.cache[key]; ok {
		return value, nil
	}
	return nil, verror.New(verror.ErrNoExist, ctx, key)
}

// getWithTypeCheck gets the key and tests if its type matches the given time, erroring if it does
// not.
// This exists mostly to shorted the Get* methods below.
func (c *cacheImpl) getWithTypeCheck(key string, rt reflect.Type) (interface{}, error) {
	v, err := c.Get(nil, nil, key)
	if err != nil {
		return reflect.Zero(rt).Interface(), err
	}
	if !reflect.TypeOf(v).AssignableTo(rt) {
		return reflect.Zero(rt).Interface(),
			fmt.Errorf("Cannot convert %v (type %v) to type %v", v, reflect.TypeOf(v), rt)
	}
	return v, nil
}

// Same as Get, but casts the return argument to an int32.
func (c *cacheImpl) GetAsInt32(_ *context.T, _ rpc.ServerCall, key string) (int32, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(int32(0)))
	return v.(int32), err
}

// Same as Get, but casts the return argument to an int64.
func (c *cacheImpl) GetAsInt64(_ *context.T, _ rpc.ServerCall, key string) (int64, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(int64(0)))
	return v.(int64), err
}

// Same as Get, but casts the return argument to an uint8.
func (c *cacheImpl) GetAsByte(_ *context.T, _ rpc.ServerCall, key string) (byte, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(byte(0)))
	return v.(uint8), err
}

// Same as Get, but casts the return argument to an uint32.
func (c *cacheImpl) GetAsUint32(_ *context.T, _ rpc.ServerCall, key string) (uint32, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(uint32(0)))
	return v.(uint32), err
}

// Same as Get, but casts the return argument to an uint64.
func (c *cacheImpl) GetAsUint64(_ *context.T, _ rpc.ServerCall, key string) (uint64, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(uint64(0)))
	return v.(uint64), err
}

// Same as Get, but casts the return argument to a float32.
func (c *cacheImpl) GetAsFloat32(_ *context.T, _ rpc.ServerCall, key string) (float32, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(float32(0)))
	return v.(float32), err
}

// Same as Get, but casts the return argument to a float64.
func (c *cacheImpl) GetAsFloat64(_ *context.T, _ rpc.ServerCall, key string) (float64, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(float64(0)))
	return v.(float64), err
}

// Same as Get, but casts the return argument to a string.
func (c *cacheImpl) GetAsString(_ *context.T, _ rpc.ServerCall, key string) (string, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(""))
	return v.(string), err
}

// Same as Get, but casts the return argument to a bool.
func (c *cacheImpl) GetAsBool(_ *context.T, _ rpc.ServerCall, key string) (bool, error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf(false))
	return v.(bool), err
}

// Same as Get, but converts the string return argument to an error.
func (c *cacheImpl) GetAsError(_ *context.T, _ rpc.ServerCall, key string) (storedError error, callError error) {
	v, err := c.getWithTypeCheck(key, reflect.TypeOf([]error{}).Elem())
	return v.(error), err
}

// AsMap returns the full contents of the cache as a map.
func (c *cacheImpl) AsMap(*context.T, rpc.ServerCall) (map[string]*vdl.Value, error) {
	return c.cache, nil
}

// KeyValuePairs returns the full contents of the cache as a slice of pairs.
func (c *cacheImpl) KeyValuePairs(*context.T, rpc.ServerCall) ([]test_service.KeyValuePair, error) {
	kvp := make([]test_service.KeyValuePair, 0, len(c.cache))
	for key, val := range c.cache {
		kvp = append(kvp, test_service.KeyValuePair{key, val})
	}
	return kvp, nil
}

// MostRecentSet returns the key and value and the timestamp for the most
// recent set operation
// TODO(bprosnitz) support type types and change time to native time type
func (c *cacheImpl) MostRecentSet(ctx *context.T, _ rpc.ServerCall) (test_service.KeyValuePair, int64, error) {
	var err error
	if c.lastUpdateTime.IsZero() {
		err = verror.New(verror.ErrNoExist, ctx)
	}
	return c.mostRecent, c.lastUpdateTime.Unix(), err
}

// KeyPage indexes into the keys (in alphanumerically sorted order) and
// returns the indexth page of 10 keys.
func (c *cacheImpl) KeyPage(ctx *context.T, _ rpc.ServerCall, index int64) (test_service.KeyPageResult, error) {
	results := test_service.KeyPageResult{}

	keys := sort.StringSlice{}
	for key, _ := range c.cache {
		keys = append(keys, key)
	}
	keys.Sort()

	lowIndex := int(index) * 10
	if index < 0 || len(keys) <= lowIndex {
		return results, verror.New(errIndexOutOfBounds, ctx, index)
	}
	highIndex := lowIndex + 9
	if highIndex > len(keys)-1 {
		highIndex = len(keys) - 1
	}

	for i := 0; lowIndex+i <= highIndex; i++ {
		results[i] = keys[lowIndex+i]
	}

	return results, nil
}

// Size returns the total number of entries in the cache.
func (c *cacheImpl) Size(*context.T, rpc.ServerCall) (int64, error) {
	return int64(len(c.cache)), nil
}

// MultiGet handles a stream of get requests.  Returns an error if one of the
// keys in the stream is not in the map or if there was an issue reading
// the stream.
func (c *cacheImpl) MultiGet(ctx *context.T, call test_service.CacheMultiGetServerCall) error {
	for call.RecvStream().Advance() {
		key := call.RecvStream().Value()
		value, ok := c.cache[key]
		if !ok {
			return verror.New(verror.ErrNoExist, ctx, key)
		}
		call.SendStream().Send(value)
	}
	return call.RecvStream().Err()
}
