// 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->globalPath().h.data());
  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->GetOutEdges();
  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->globalPath().h.data() + "'");
      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->globalPath().h.str_view().AsString() +
              "' 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->SetRestat();

  // 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, file->scope());
  return parser.Load(file->globalPath().h.data(), err);
}
