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

import (
	"encoding/json"
	"io"
	"os"
	"path"
	"strings"
	"sync"

	"v.io/x/lib/vlog"
)

type store struct {
	l   sync.Mutex
	mt  *mountTable
	dir string
	enc *json.Encoder
	f   *os.File
}

type storeElement struct {
	N string // Name of affected node
	V VersionedPermissions
	D bool   // True if the subtree at N has been deleted
	C string // Creator
}

// newPersistentStore will read the permissions log from the directory and apply them to the
// in memory tree.  It will then write a new file from the in memory tree and any new permission
// changes will be appened to this file.  By writing into a new file, we effectively compress
// the permissions file since any set permissions that have been deleted or overwritten will be
// lost.
//
// The code manages three files in the directory 'dir':
//   persistent.permslog - the log of permissions.  A new log entry is added with each SetPermissions or
//      Delete RPC.
//   tmp.permslog - a temporary file created whenever we restart.  Once we write the current state into it,
//      it will be renamed persistent.perms becoming the new log.
//   old.permslog - the previous version of persistent.perms.  This is left around primarily for debugging
//      and as an emergency backup.
func newPersistentStore(mt *mountTable, dir string) persistence {
	s := &store{mt: mt, dir: dir}
	file := path.Join(dir, "persistent.permslog")
	tmp := path.Join(dir, "tmp.permslog")
	old := path.Join(dir, "old.permslog")

	// If the permissions file doesn't exist, try renaming the temporary one.
	f, err := os.Open(file)
	if err != nil {
		if !os.IsNotExist(err) {
			vlog.Fatalf("cannot open %s: %s", file, err)
		}
		os.Rename(tmp, file)
		if f, err = os.Open(file); err != nil && !os.IsNotExist(err) {
			vlog.Fatalf("cannot open %s: %s", file, err)
		}
	} else {
		os.Remove(tmp)
	}

	// Parse the permissions file and apply it to the in memory tree.
	if f != nil {
		if err := s.parseLogFile(f); err != nil {
			f.Close()
			// Log the error but keep going.  There's not much else we can do.
			vlog.Infof("parsing old persistent permissions file %s: %s", file, err)
		}
		f.Close()
	}

	// Write the permissions to a temporary file.  This compresses
	// the file since it writes out only the end state.
	f, err = os.OpenFile(tmp, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)
	if err != nil {
		// Log the error but keep going, don't compress, just append to the current file.
		vlog.Infof("can't rewrite persistent permissions file %s: %s", file, err)
		if f, err = os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600); err != nil {
			vlog.Fatalf("can't append to log %s: %s", file, err)
		}
		f.Seek(0, 2)
		s.enc = json.NewEncoder(f)
		return s
	}
	s.enc = json.NewEncoder(f)
	s.depthFirstPersist(mt.root, "")
	f.Close()

	// Switch names and remove the old file.
	if err := os.Remove(old); err != nil {
		vlog.Infof("removing %s: %s", old, err)
	}
	if err := os.Rename(file, old); err != nil {
		vlog.Infof("renaming %s to %s: %s", file, old, err)
	}
	if err := os.Rename(tmp, file); err != nil {
		vlog.Fatalf("renaming %s to %s: %s", tmp, file, err)
	}

	// Reopen the new log file.  We could have just kept around the encoder used
	// to create it but that assumes that, after the Rename above, the s.f still
	// points to the same file.  Only true on Unix like file systems.
	f, err = os.OpenFile(file, os.O_WRONLY|os.O_APPEND, 0600)
	if err != nil {
		vlog.Fatalf("can't open %s: %s", file, err)
	}
	f.Seek(0, 2)
	s.enc = json.NewEncoder(f)
	return s
}

// parseLogFile reads a file and parses the contained VersionedPermissions .
func (s *store) parseLogFile(f *os.File) error {
	if f == nil {
		return nil
	}
	vlog.VI(2).Infof("parseLogFile(%s)", f.Name())
	mt := s.mt
	decoder := json.NewDecoder(f)
	for {
		var e storeElement
		if err := decoder.Decode(&e); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		elems := strings.Split(e.N, "/")
		n, err := mt.findNode(nil, nil, elems, true, nil, nil)
		if n != nil || err == nil {
			n.creator = e.C
			if e.D {
				mt.deleteNode(n.parent, elems[len(elems)-1])
				vlog.VI(2).Infof("deleted %s", e.N)
			} else {
				n.vPerms = &e.V
				n.explicitPermissions = true
				vlog.VI(2).Infof("added versions permissions %v to %s", e.V, e.N)
			}
		}
		n.parent.Unlock()
		n.Unlock()
	}
	return nil
}

// depthFirstPersist performs a recursive depth first traversal logging any explicit permissions.
// Doing this immediately after reading in a log file effectively compresses the log file since
// any duplicate or deleted entries disappear.
func (s *store) depthFirstPersist(n *node, name string) {
	if n.explicitPermissions {
		s.persistPerms(name, n.creator, n.vPerms)
	}
	for nodeName, c := range n.children {
		s.depthFirstPersist(c, path.Join(name, nodeName))
	}
}

// persistPerms appends a changed permission to the log.
func (s *store) persistPerms(name, creator string, vPerms *VersionedPermissions) error {
	s.l.Lock()
	defer s.l.Unlock()
	e := storeElement{N: name, V: *vPerms, C: creator}
	return s.enc.Encode(&e)
}

// persistDelete appends a single deletion to the log.
func (s *store) persistDelete(name string) error {
	s.l.Lock()
	defer s.l.Unlock()
	e := storeElement{N: name, D: true}
	return s.enc.Encode(&e)
}

func (s *store) close() {
	s.f.Close()
}
