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

// +build ignore

#include "exec.h"

#include <stdio.h>
#include <stdlib.h>

#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>

#include "command.h"
#include "dep.h"
#include "eval.h"
#include "fileutil.h"
#include "flags.h"
#include "log.h"
#include "string_piece.h"
#include "strutil.h"
#include "symtab.h"
#include "value.h"
#include "var.h"

namespace {

const double kNotExist = -2.0;
const double kProcessing = -1.0;

class Executor {
 public:
  explicit Executor(Evaluator* ev)
      : ce_(ev) {
    shell_ = ev->EvalVar(kShellSym);
  }

  double ExecNode(DepNode* n, DepNode* needed_by) {
    auto found = done_.find(n->output);
    if (found != done_.end()) {
      if (found->second == kProcessing) {
        WARN("Circular %s <- %s dependency dropped.",
             needed_by ? needed_by->output.c_str() : "(null)",
             n->output.c_str());
      }
      return found->second;
    }
    done_[n->output] = kProcessing;
    double output_ts = GetTimestamp(n->output.c_str());

    LOG("ExecNode: %s for %s",
        n->output.c_str(),
        needed_by ? needed_by->output.c_str() : "(null)");

    if (!n->has_rule && output_ts == kNotExist && !n->is_phony) {
      if (needed_by) {
        ERROR("*** No rule to make target '%s', needed by '%s'.",
              n->output.c_str(), needed_by->output.c_str());
      } else {
        ERROR("*** No rule to make target '%s'.", n->output.c_str());
      }
    }

    double latest = kProcessing;
    for (DepNode* d : n->order_onlys) {
      if (Exists(d->output.str())) {
        continue;
      }
      double ts = ExecNode(d, n);
      if (latest < ts)
        latest = ts;
    }

    for (DepNode* d : n->deps) {
      double ts = ExecNode(d, n);
      if (latest < ts)
        latest = ts;
    }

    if (output_ts >= latest && !n->is_phony) {
      done_[n->output] = output_ts;
      return output_ts;
    }

    vector<Command*> commands;
    ce_.Eval(n, &commands);
    for (Command* command : commands) {
      num_commands_ += 1;
      if (command->echo) {
        printf("%s\n", command->cmd.c_str());
        fflush(stdout);
      }
      if (!g_is_dry_run) {
        string out;
        int result = RunCommand(shell_, command->cmd.c_str(),
                                RedirectStderr::STDOUT,
                                &out);
        printf("%s", out.c_str());
        if (result != 0) {
          if (command->ignore_error) {
            fprintf(stderr, "[%s] Error %d (ignored)\n",
                    command->output.c_str(), WEXITSTATUS(result));
          } else {
            fprintf(stderr, "*** [%s] Error %d\n",
                    command->output.c_str(), WEXITSTATUS(result));
            exit(1);
          }
        }
      }
      delete command;
    }

    done_[n->output] = output_ts;
    return output_ts;
  }

  uint64_t Count() {
    return num_commands_;
  }

 private:
  CommandEvaluator ce_;
  unordered_map<Symbol, double> done_;
  string shell_;
  uint64_t num_commands_;
};

}  // namespace

void Exec(const vector<DepNode*>& roots, Evaluator* ev) {
  unique_ptr<Executor> executor(new Executor(ev));
  for (DepNode* root : roots) {
    executor->ExecNode(root, NULL);
  }
  if (executor->Count() == 0) {
    for (DepNode* root : roots) {
      printf("kati: Nothing to be done for `%s'.\n", root->output.c_str());
    }
  }
}
