// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dyndep.h"

#include <assert.h>
#include <stdio.h>

#include "debug_flags.h"
#include "disk_interface.h"
#include "dyndep_parser.h"
#include "graph.h"
#include "state.h"
#include "util.h"

bool DyndepLoader::LoadDyndeps(Node* node, std::string* err) const {
  DyndepFile ddf;
  return LoadDyndeps(node, &ddf, err);
}

bool DyndepLoader::LoadDyndeps(Node* node, DyndepFile* ddf,
                               std::string* err) const {
  // We are loading the dyndep file now so it is no longer pending.
  node->set_dyndep_pending(false);

  // Load the dyndep information from the file.
  EXPLAIN("loading dyndep file '%s'", node->path().c_str());
  if (!LoadDyndepFile(node, ddf, err))
    return false;

  // Update each edge that specified this node as its dyndep binding.
  std::vector<Edge*> const& out_edges = node->out_edges();
  for (std::vector<Edge*>::const_iterator oe = out_edges.begin();
       oe != out_edges.end(); ++oe) {
    Edge* const edge = *oe;
    if (edge->dyndep_ != node)
      continue;

    DyndepFile::iterator ddi = ddf->find(edge);
    if (ddi == ddf->end()) {
      *err = ("'" + edge->outputs_[0]->path() + "' "
              "not mentioned in its dyndep file "
              "'" + node->path() + "'");
      return false;
    }

    ddi->second.used_ = true;
    Dyndeps const& dyndeps = ddi->second;
    if (!UpdateEdge(edge, &dyndeps, err)) {
      return false;
    }
  }

  // Reject extra outputs in dyndep file.
  for (DyndepFile::const_iterator oe = ddf->begin(); oe != ddf->end();
       ++oe) {
    if (!oe->second.used_) {
      Edge* const edge = oe->first;
      *err = ("dyndep file '" + node->path() + "' mentions output "
              "'" + edge->outputs_[0]->path() + "' whose build statement "
              "does not have a dyndep binding for the file");
      return false;
    }
  }

  return true;
}

bool DyndepLoader::UpdateEdge(Edge* edge, Dyndeps const* dyndeps,
                              std::string* err) const {
  // Add dyndep-discovered bindings to the edge.
  // We know the edge already has its own binding
  // scope because it has a "dyndep" binding.
  if (dyndeps->restat_)
    edge->env_->AddBinding("restat", "1");

  // Add the dyndep-discovered outputs to the edge.
  edge->outputs_.insert(edge->outputs_.end(),
                        dyndeps->implicit_outputs_.begin(),
                        dyndeps->implicit_outputs_.end());
  edge->implicit_outs_ += dyndeps->implicit_outputs_.size();

  // Add this edge as incoming to each new output.
  for (std::vector<Node*>::const_iterator i =
           dyndeps->implicit_outputs_.begin();
       i != dyndeps->implicit_outputs_.end(); ++i) {
    if ((*i)->in_edge() != NULL) {
      *err = "multiple rules generate " + (*i)->path();
      return false;
    }
    (*i)->set_in_edge(edge);
  }

  // Add the dyndep-discovered inputs to the edge.
  edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
                       dyndeps->implicit_inputs_.begin(),
                       dyndeps->implicit_inputs_.end());
  edge->implicit_deps_ += dyndeps->implicit_inputs_.size();

  // Add this edge as outgoing from each new input.
  for (std::vector<Node*>::const_iterator i =
           dyndeps->implicit_inputs_.begin();
       i != dyndeps->implicit_inputs_.end(); ++i)
    (*i)->AddOutEdge(edge);

  return true;
}

bool DyndepLoader::LoadDyndepFile(Node* file, DyndepFile* ddf,
                                  std::string* err) const {
  DyndepParser parser(state_, disk_interface_, ddf);
  return parser.Load(file->path(), err);
}
