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

// 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)
		if n != nil || err == nil {
			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.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 string, vPerms *VersionedPermissions) error {
	s.l.Lock()
	defer s.l.Unlock()
	e := storeElement{N: name, V: *vPerms}
	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()
}
