// Copyright 2016 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 "regen.h"

#include <sys/stat.h>

#include <algorithm>
#include <memory>
#include <mutex>
#include <vector>

#include "fileutil.h"
#include "find.h"
#include "io.h"
#include "log.h"
#include "ninja.h"
#include "stats.h"
#include "strutil.h"
#include "thread_pool.h"

namespace {

#define RETURN_TRUE do {                        \
      if (g_flags.dump_kati_stamp)              \
        needs_regen_ = true;                    \
      else                                      \
        return true;                            \
    } while (0)

bool ShouldIgnoreDirty(StringPiece s) {
  Pattern pat(g_flags.ignore_dirty_pattern);
  Pattern nopat(g_flags.no_ignore_dirty_pattern);
  return pat.Match(s) && !nopat.Match(s);
}

class StampChecker {
  struct GlobResult {
    string pat;
    vector<string> result;
  };

  struct ShellResult {
    string cmd;
    string result;
    vector<string> missing_dirs;
    vector<string> read_dirs;
    bool has_condition;
  };

 public:
  StampChecker()
      : needs_regen_(false) {
  }

  ~StampChecker() {
    for (GlobResult* gr : globs_) {
      delete gr;
    }
    for (ShellResult* sr : commands_) {
      delete sr;
    }
  }

  bool NeedsRegen(double start_time, const string& orig_args) {
    if (IsMissingOutputs())
      RETURN_TRUE;

    if (CheckStep1(orig_args))
      RETURN_TRUE;

    if (CheckStep2())
      RETURN_TRUE;

    if (!needs_regen_) {
      FILE* fp = fopen(GetNinjaStampFilename().c_str(), "rb+");
      if (!fp)
        return true;
      ScopedFile sfp(fp);
      if (fseek(fp, 0, SEEK_SET) < 0)
        PERROR("fseek");
      size_t r = fwrite(&start_time, sizeof(start_time), 1, fp);
      CHECK(r == 1);
    }
    return needs_regen_;
  }

 private:
  bool IsMissingOutputs() {
    if (!Exists(GetNinjaFilename())) {
      fprintf(stderr, "%s is missing, regenerating...\n",
              GetNinjaFilename().c_str());
      return true;
    }
    if (!Exists(GetNinjaShellScriptFilename())) {
      fprintf(stderr, "%s is missing, regenerating...\n",
              GetNinjaShellScriptFilename().c_str());
      return true;
    }
    return false;
  }

  bool CheckStep1(const string& orig_args) {
#define LOAD_INT(fp) ({                                                 \
        int v = LoadInt(fp);                                            \
        if (v < 0) {                                                    \
          fprintf(stderr, "incomplete kati_stamp, regenerating...\n");  \
          RETURN_TRUE;                                                  \
        }                                                               \
        v;                                                              \
      })

#define LOAD_STRING(fp, s) ({                                           \
        if (!LoadString(fp, s)) {                                       \
          fprintf(stderr, "incomplete kati_stamp, regenerating...\n");  \
          RETURN_TRUE;                                                  \
        }                                                               \
      })

    const string& stamp_filename = GetNinjaStampFilename();
    FILE* fp = fopen(stamp_filename.c_str(), "rb");
    if (!fp) {
      if (g_flags.dump_kati_stamp)
        printf("%s: %s\n", stamp_filename.c_str(), strerror(errno));
      return true;
    }
    ScopedFile sfp(fp);

    double gen_time;
    size_t r = fread(&gen_time, sizeof(gen_time), 1, fp);
    gen_time_ = gen_time;
    if (r != 1) {
      fprintf(stderr, "incomplete kati_stamp, regenerating...\n");
      RETURN_TRUE;
    }
    if (g_flags.dump_kati_stamp)
      printf("Generated time: %f\n", gen_time);

    string s, s2;
    int num_files = LOAD_INT(fp);
    for (int i = 0; i < num_files; i++) {
      LOAD_STRING(fp, &s);
      double ts = GetTimestamp(s);
      if (gen_time < ts) {
        if (g_flags.regen_ignoring_kati_binary) {
          string kati_binary;
          GetExecutablePath(&kati_binary);
          if (s == kati_binary) {
            fprintf(stderr, "%s was modified, ignored.\n", s.c_str());
            continue;
          }
        }
        if (ShouldIgnoreDirty(s)) {
          if (g_flags.dump_kati_stamp)
            printf("file %s: ignored (%f)\n", s.c_str(), ts);
          continue;
        }
        if (g_flags.dump_kati_stamp)
          printf("file %s: dirty (%f)\n", s.c_str(), ts);
        else
          fprintf(stderr, "%s was modified, regenerating...\n", s.c_str());
        RETURN_TRUE;
      } else if (g_flags.dump_kati_stamp) {
        printf("file %s: clean (%f)\n", s.c_str(), ts);
      }
    }

    int num_undefineds = LOAD_INT(fp);
    for (int i = 0; i < num_undefineds; i++) {
      LOAD_STRING(fp, &s);
      if (getenv(s.c_str())) {
        if (g_flags.dump_kati_stamp) {
          printf("env %s: dirty (unset => %s)\n", s.c_str(), getenv(s.c_str()));
        } else {
          fprintf(stderr, "Environment variable %s was set, regenerating...\n",
                  s.c_str());
        }
        RETURN_TRUE;
      } else if (g_flags.dump_kati_stamp) {
        printf("env %s: clean (unset)\n", s.c_str());
      }
    }

    int num_envs = LOAD_INT(fp);
    for (int i = 0; i < num_envs; i++) {
      LOAD_STRING(fp, &s);
      StringPiece val(getenv(s.c_str()));
      LOAD_STRING(fp, &s2);
      if (val != s2) {
        if (g_flags.dump_kati_stamp) {
          printf("env %s: dirty (%s => %.*s)\n",
                 s.c_str(), s2.c_str(), SPF(val));
        } else {
          fprintf(stderr, "Environment variable %s was modified (%s => %.*s), "
                  "regenerating...\n",
                  s.c_str(), s2.c_str(), SPF(val));
        }
        RETURN_TRUE;
      } else if (g_flags.dump_kati_stamp) {
        printf("env %s: clean (%.*s)\n", s.c_str(), SPF(val));
      }
    }

    int num_globs = LOAD_INT(fp);
    string pat;
    for (int i = 0; i < num_globs; i++) {
      GlobResult* gr = new GlobResult;
      globs_.push_back(gr);

      LOAD_STRING(fp, &gr->pat);
      int num_files = LOAD_INT(fp);
      gr->result.resize(num_files);
      for (int j = 0; j < num_files; j++) {
        LOAD_STRING(fp, &gr->result[j]);
      }
    }

    int num_crs = LOAD_INT(fp);
    for (int i = 0; i < num_crs; i++) {
      ShellResult* sr = new ShellResult;
      commands_.push_back(sr);
      LOAD_STRING(fp, &sr->cmd);
      LOAD_STRING(fp, &sr->result);
      sr->has_condition = LOAD_INT(fp);
      if (!sr->has_condition)
        continue;

      int num_missing_dirs = LOAD_INT(fp);
      for (int j = 0; j < num_missing_dirs; j++) {
        LOAD_STRING(fp, &s);
        sr->missing_dirs.push_back(s);
      }
      int num_read_dirs = LOAD_INT(fp);
      for (int j = 0; j < num_read_dirs; j++) {
        LOAD_STRING(fp, &s);
        sr->read_dirs.push_back(s);
      }
    }

    LoadString(fp, &s);
    if (orig_args != s) {
      fprintf(stderr, "arguments changed, regenerating...\n");
      RETURN_TRUE;
    }

    return needs_regen_;
  }

  bool CheckGlobResult(const GlobResult* gr, string* err) {
    COLLECT_STATS("glob time (regen)");
    vector<string>* files;
    Glob(gr->pat.c_str(), &files);
    sort(files->begin(), files->end());
    bool needs_regen = files->size() != gr->result.size();
    for (size_t i = 0; i < gr->result.size(); i++) {
      if (!needs_regen) {
        if ((*files)[i] != gr->result[i]) {
          needs_regen = true;
          break;
        }
      }
    }
    if (needs_regen) {
      if (ShouldIgnoreDirty(gr->pat)) {
        if (g_flags.dump_kati_stamp) {
          printf("wildcard %s: ignored\n", gr->pat.c_str());
        }
        return false;
      }
      if (g_flags.dump_kati_stamp) {
        printf("wildcard %s: dirty\n", gr->pat.c_str());
      } else {
        *err = StringPrintf("wildcard(%s) was changed, regenerating...\n",
                            gr->pat.c_str());
      }
    } else if (g_flags.dump_kati_stamp) {
      printf("wildcard %s: clean\n", gr->pat.c_str());
    }
    return needs_regen;
  }

  bool ShouldRunCommand(const ShellResult* sr) {
    if (!sr->has_condition)
      return true;

    COLLECT_STATS("stat time (regen)");
    for (const string& dir : sr->missing_dirs) {
      if (Exists(dir))
        return true;
    }
    for (const string& dir : sr->read_dirs) {
      // We assume we rarely do a significant change for the top
      // directory which affects the results of find command.
      if (dir == "" || dir == "." || ShouldIgnoreDirty(dir))
        continue;

      struct stat st;
      if (lstat(dir.c_str(), &st) != 0) {
        return true;
      }
      double ts = GetTimestampFromStat(st);
      if (gen_time_ < ts) {
        return true;
      }
      if (S_ISLNK(st.st_mode)) {
        ts = GetTimestamp(dir);
        if (ts < 0 || gen_time_ < ts)
          return true;
      }
    }
    return false;
  }

  bool CheckShellResult(const ShellResult* sr, string* err) {
    if (!ShouldRunCommand(sr)) {
      if (g_flags.dump_kati_stamp)
        printf("shell %s: clean (no rerun)\n", sr->cmd.c_str());
      return false;
    }

    FindCommand fc;
    if (fc.Parse(sr->cmd) &&
        !fc.chdir.empty() && ShouldIgnoreDirty(fc.chdir)) {
      if (g_flags.dump_kati_stamp)
        printf("shell %s: ignored\n", sr->cmd.c_str());
      return false;
    }

    COLLECT_STATS_WITH_SLOW_REPORT("shell time (regen)", sr->cmd.c_str());
    string result;
    RunCommand("/bin/sh", sr->cmd, RedirectStderr::DEV_NULL, &result);
    FormatForCommandSubstitution(&result);
    if (sr->result != result) {
      if (g_flags.dump_kati_stamp) {
        printf("shell %s: dirty\n", sr->cmd.c_str());
      } else {
        *err = StringPrintf("$(shell %s) was changed, regenerating...\n",
                            sr->cmd.c_str());
        //*err += StringPrintf("%s => %s\n", expected.c_str(), result.c_str());
      }
      return true;
    } else if (g_flags.dump_kati_stamp) {
      printf("shell %s: clean (rerun)\n", sr->cmd.c_str());
    }
    return false;
  }

  bool CheckStep2() {
    unique_ptr<ThreadPool> tp(NewThreadPool(g_flags.num_jobs));

    tp->Submit([this]() {
        string err;
        // TODO: Make glob cache thread safe and create a task for each glob.
        for (GlobResult* gr : globs_) {
          if (CheckGlobResult(gr, &err)) {
            unique_lock<mutex> lock(mu_);
            if (!needs_regen_) {
              needs_regen_ = true;
              msg_ = err;
            }
            break;
          }
        }
      });

    for (ShellResult* sr : commands_) {
      tp->Submit([this, sr]() {
          string err;
          if (CheckShellResult(sr, &err)) {
            unique_lock<mutex> lock(mu_);
            if (!needs_regen_) {
              needs_regen_ = true;
              msg_ = err;
            }
          }
        });
    }

    tp->Wait();
    if (needs_regen_) {
      fprintf(stderr, "%s", msg_.c_str());
    }
    return needs_regen_;
  }

 private:
  double gen_time_;
  vector<GlobResult*> globs_;
  vector<ShellResult*> commands_;
  mutex mu_;
  bool needs_regen_;
  string msg_;
};

}  // namespace

bool NeedsRegen(double start_time, const string& orig_args) {
  return StampChecker().NeedsRegen(start_time, orig_args);
}
