/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  Regents of the University of California
 *
 * This file is part of NSL (NDN Signature Logger).
 * See AUTHORS.md for complete list of NSL authors and contributors.
 *
 * NSL is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NSL, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of nsl authors and contributors.
 */

#include "merkle-tree.hpp"

namespace nsl {

MerkleTree::MerkleTree(Db& db)
  : m_db(db)
  , m_nextLeafSeqNo(0)
{
}

MerkleTree::MerkleTree(const Name& loggerName, Db& db)
  : m_loggerName(loggerName)
  , m_db(db)
  , m_nextLeafSeqNo(0)
{
  loadPendingSubTrees();
}

MerkleTree::~MerkleTree()
{
  savePendingTree();
}

void
MerkleTree::setLoggerName(const Name& loggerName)
{
  m_loggerName = loggerName;
}

bool
MerkleTree::addLeaf(const NonNegativeInteger& seqNo, ndn::ConstBufferPtr hash)
{
  auto baseTree = m_pendingTrees[SubTreeBinary::SUB_TREE_DEPTH - 1];
  BOOST_ASSERT(baseTree != nullptr);

  NodePtr leaf = make_shared<Node>(seqNo, 0, seqNo + 1, hash);
  return baseTree->addLeaf(leaf);
}

void
MerkleTree::savePendingTree()
{
  size_t level = m_rootSubTree->getPeakIndex().level;
  size_t step = SubTreeBinary::SUB_TREE_DEPTH - 1;

  for (size_t i = level; i > 0; i -= step) {
    auto pendingTree = m_pendingTrees[i];
    BOOST_ASSERT(pendingTree != nullptr);

    auto data = pendingTree->encode();
    if (data != nullptr) {
      m_db.insertSubTreeData(pendingTree->getPeakIndex().level, pendingTree->getPeakIndex().seqNo,
                             *data, false, pendingTree->getNextLeafSeqNo());
    }
  }
}

shared_ptr<Data>
MerkleTree::getPendingSubTreeData(size_t level)
{
  auto it = m_pendingTrees.find(level);
  if (it != m_pendingTrees.end())
    return it->second->encode();
  else
    return nullptr;
}

// private:
void
MerkleTree::loadPendingSubTrees()
{
  std::vector<shared_ptr<Data>> subtreeDatas = m_db.getPendingSubTrees();

  shared_ptr<SubTreeBinary> subtree;
  if (subtreeDatas.empty()) {
    subtree = make_shared<SubTreeBinary>(m_loggerName,
      Node::Index(0, SubTreeBinary::SUB_TREE_DEPTH - 1),
      [this] (const Node::Index& idx) {
        // std::cerr << "complete: " << idx.level << ", " << idx.seqNo << std::endl;
        this->getNewRoot(idx);
      },
      [this] (const Node::Index& idx,
              const NonNegativeInteger& seqNo,
              ndn::ConstBufferPtr hash) {
        // std::cerr << "update: " << idx.level << ", " << idx.seqNo << std::endl;
        // std::cerr << "seqNo: " << seqNo << std::endl;
        this->m_nextLeafSeqNo = seqNo;
        this->m_hash = hash;
      });
    m_pendingTrees[SubTreeBinary::SUB_TREE_DEPTH - 1] = subtree;
    m_rootSubTree = subtree;
    return;
  }

  subtree = make_shared<SubTreeBinary>(m_loggerName,
    [this] (const Node::Index& idx) { this->getNewRoot(idx); },
    [this] (const Node::Index& idx,
            const NonNegativeInteger& seqNo,
            ndn::ConstBufferPtr hash) {
      this->m_nextLeafSeqNo = seqNo;
      this->m_hash = hash;
    });

  subtree->decode(*subtreeDatas[0]);
  m_pendingTrees[subtree->getPeakIndex().level] = subtree;
  m_rootSubTree = subtree;

  shared_ptr<SubTreeBinary> parentTree = subtree;
  for (size_t i = 1; i < subtreeDatas.size(); i++) {
    subtree = make_shared<SubTreeBinary>(m_loggerName,
      [this] (const Node::Index& idx) {
        this->getNewSibling(idx);
      },
      [parentTree] (const Node::Index&,
           const NonNegativeInteger& seqNo,
           ndn::ConstBufferPtr hash) {
        parentTree->updateLeaf(seqNo, hash);
      });

    subtree->decode(*subtreeDatas[i]);
    if (parentTree->getPeakIndex().level + 1 - SubTreeBinary::SUB_TREE_DEPTH !=
        subtree->getPeakIndex().level)
      throw Error("loadPendingSubTrees: inconsistent pending subtree level");

    if (parentTree->getNextLeafSeqNo() != subtree->getNextLeafSeqNo())
      throw Error("loadPendingSubTrees: inconsistent pending subtree next leaf seqNo");

    m_pendingTrees[subtree->getPeakIndex().level] = subtree;
    parentTree = subtree;
  }
}

void
MerkleTree::getNewRoot(const Node::Index& idx)
{
  // save the old root tree into db
  auto oldRoot = m_pendingTrees[idx.level];
  BOOST_ASSERT(oldRoot != nullptr);
  m_db.insertSubTreeData(idx.level, idx.seqNo, *oldRoot->encode());

  // create a new root tree
  Node::Index newRootIdx(0, idx.level + SubTreeBinary::SUB_TREE_DEPTH - 1);
  auto newRoot = make_shared<SubTreeBinary>(m_loggerName, newRootIdx,
    [this] (const Node::Index& idx) {
      // std::cerr << "complete: " << idx.level << ", " << idx.seqNo << std::endl;
      this->getNewRoot(idx);
    },
    [this] (const Node::Index& index,
         const NonNegativeInteger& seqNo,
         ndn::ConstBufferPtr hash) {
      // std::cerr << "update: " << index.level << ", " << index.seqNo << std::endl;
      // std::cerr << "seqNo: " << seqNo << std::endl;
      this->m_nextLeafSeqNo = seqNo;
      this->m_hash = hash;
    });

  m_pendingTrees[newRoot->getPeakIndex().level] = newRoot;
  m_rootSubTree = newRoot;

  bool result = newRoot->updateLeaf(idx.seqNo + idx.range, oldRoot->getRoot()->getHash());
  BOOST_ASSERT(result);

  // create a sibling
  getNewSibling(idx);
}

void
MerkleTree::getNewSibling(const Node::Index& idx)
{
  // save old sibling
  auto oldSibling = m_pendingTrees[idx.level];
  BOOST_ASSERT(oldSibling != nullptr);
  m_db.insertSubTreeData(idx.level, idx.seqNo, *oldSibling->encode());

  // get parent tree
  Node::Index parentIdx(0, idx.level + SubTreeBinary::SUB_TREE_DEPTH - 1);
  auto parent = m_pendingTrees[parentIdx.level];
  BOOST_ASSERT(parent != nullptr);

  // create a new sibling
  Node::Index newSiblingIdx(idx.seqNo + idx.range, idx.level);
  // std::cerr << "new Sibling: " << newSiblingIdx.level << ", " << newSiblingIdx.seqNo << std::endl;
  auto newSibling = make_shared<SubTreeBinary>(m_loggerName, newSiblingIdx,
    [this] (const Node::Index& idx) { this->getNewSibling(idx); },
    [parent] (const Node::Index& index,
         const NonNegativeInteger& seqNo,
         ndn::ConstBufferPtr hash) {
      // std::cerr << "update: " << index.level << ", " << index.seqNo << std::endl;
      // std::cerr << "seqNo: " << seqNo << std::endl;
      // std::cerr << "parent: " << parent->getRoot()->getIndex().level << ", " <<
      //                            parent->getRoot()->getIndex().seqNo << std::endl;
      bool result = parent->updateLeaf(seqNo, hash);
      BOOST_ASSERT(result);
    });

  m_pendingTrees[newSibling->getPeakIndex().level] = newSibling;
}

}// namespace nsl
