// Copyright 2011 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 "clean.h"

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

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

Cleaner::Cleaner(State* state, const BuildConfig& config)
  : state_(state),
    config_(config),
    removed_(),
    cleaned_files_count_(0),
    disk_interface_(new RealDiskInterface),
    status_(0) {
}

Cleaner::Cleaner(State* state,
                 const BuildConfig& config,
                 DiskInterface* disk_interface)
  : state_(state),
    config_(config),
    removed_(),
    cleaned_files_count_(0),
    disk_interface_(disk_interface),
    status_(0) {
}

int Cleaner::RemoveFile(const string& path) {
  return disk_interface_->RemoveFile(path);
}

bool Cleaner::FileExists(const string& path) {
  return disk_interface_->Stat(path) > 0;
}

void Cleaner::Report(const string& path) {
  ++cleaned_files_count_;
  if (IsVerbose())
    printf("Remove %s\n", path.c_str());
}

void Cleaner::Remove(const string& path) {
  if (!IsAlreadyRemoved(path)) {
    removed_.insert(path);
    if (config_.dry_run) {
      if (FileExists(path))
        Report(path);
    } else {
      int ret = RemoveFile(path);
      if (ret == 0)
        Report(path);
      else if (ret == -1)
        status_ = 1;
    }
  }
}

bool Cleaner::IsAlreadyRemoved(const string& path) {
  set<string>::iterator i = removed_.find(path);
  return (i != removed_.end());
}

void Cleaner::PrintHeader() {
  if (config_.verbosity == BuildConfig::QUIET)
    return;
  printf("Cleaning...");
  if (IsVerbose())
    printf("\n");
  else
    printf(" ");
}

void Cleaner::PrintFooter() {
  if (config_.verbosity == BuildConfig::QUIET)
    return;
  printf("%d files.\n", cleaned_files_count_);
}

int Cleaner::CleanAll(bool generator) {
  Reset();
  PrintHeader();
  for (vector<Edge*>::iterator e = state_->edges_.begin();
       e != state_->edges_.end(); ++e) {
    // Do not try to remove phony targets
    if ((*e)->is_phony())
      continue;
    // Do not remove generator's files unless generator specified.
    if (!generator && (*e)->rule().generator())
      continue;
    for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
         out_node != (*e)->outputs_.end(); ++out_node) {
      Remove((*out_node)->path());
    }
    // Remove the depfile
    if (!(*e)->rule().depfile().empty())
      Remove((*e)->EvaluateDepFile());
    // Remove the response file
    if ((*e)->HasRspFile()) 
      Remove((*e)->GetRspFile());      
  }
  PrintFooter();
  return status_;
}

void Cleaner::DoCleanTarget(Node* target) {
  if (Edge* e = target->in_edge()) {
    // Do not try to remove phony targets
    if (!e->is_phony()) {
      Remove(target->path());
      if (!target->in_edge()->rule().depfile().empty())
        Remove(target->in_edge()->EvaluateDepFile());
      if (e->HasRspFile())
        Remove(e->GetRspFile());
    }
    for (vector<Node*>::iterator n = e->inputs_.begin(); n != e->inputs_.end();
         ++n) {
      DoCleanTarget(*n);
    }
  }
}

int Cleaner::CleanTarget(Node* target) {
  assert(target);

  Reset();
  PrintHeader();
  DoCleanTarget(target);
  PrintFooter();
  return status_;
}

int Cleaner::CleanTarget(const char* target) {
  assert(target);

  Reset();
  Node* node = state_->LookupNode(target);
  if (node) {
    CleanTarget(node);
  } else {
    Error("unknown target '%s'", target);
    status_ = 1;
  }
  return status_;
}

int Cleaner::CleanTargets(int target_count, char* targets[]) {
  Reset();
  PrintHeader();
  for (int i = 0; i < target_count; ++i) {
    const char* target_name = targets[i];
    Node* target = state_->LookupNode(target_name);
    if (target) {
      if (IsVerbose())
        printf("Target %s\n", target_name);
      DoCleanTarget(target);
    } else {
      Error("unknown target '%s'", target_name);
      status_ = 1;
    }
  }
  PrintFooter();
  return status_;
}

void Cleaner::DoCleanRule(const Rule* rule) {
  assert(rule);

  for (vector<Edge*>::iterator e = state_->edges_.begin();
       e != state_->edges_.end(); ++e) {
    if ((*e)->rule().name() == rule->name()) {
      for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
           out_node != (*e)->outputs_.end(); ++out_node) {
        Remove((*out_node)->path());
        if (!(*e)->rule().depfile().empty())
          Remove((*e)->EvaluateDepFile());
        if ((*e)->HasRspFile()) 
          Remove((*e)->GetRspFile());
      }
    }
  }
}

int Cleaner::CleanRule(const Rule* rule) {
  assert(rule);

  Reset();
  PrintHeader();
  DoCleanRule(rule);
  PrintFooter();
  return status_;
}

int Cleaner::CleanRule(const char* rule) {
  assert(rule);

  Reset();
  const Rule* r = state_->LookupRule(rule);
  if (r) {
    CleanRule(r);
  } else {
    Error("unknown rule '%s'", rule);
    status_ = 1;
  }
  return status_;
}

int Cleaner::CleanRules(int rule_count, char* rules[]) {
  assert(rules);

  Reset();
  PrintHeader();
  for (int i = 0; i < rule_count; ++i) {
    const char* rule_name = rules[i];
    const Rule* rule = state_->LookupRule(rule_name);
    if (rule) {
      if (IsVerbose())
        printf("Rule %s\n", rule_name);
      DoCleanRule(rule);
    } else {
      Error("unknown rule '%s'", rule_name);
      status_ = 1;
    }
  }
  PrintFooter();
  return status_;
}

void Cleaner::Reset() {
  status_ = 0;
  cleaned_files_count_ = 0;
  removed_.clear();
}
