// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(adlr): get rid of commented out lines or comment them back in.
// Look for "// re-add" next to those comments.

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <set>
#include <string>
#include <vector>

#include <gflags/gflags.h>
#include <glib.h>
#include "chromeos/obsolete_logging.h"

#include "update_engine/delta_diff_generator.h"
#include "update_engine/delta_diff_parser.h"
#include "update_engine/filesystem_copier_action.h"
// #include "update_engine/install_action.h"  // re-add
#include "update_engine/install_plan.h"
#include "update_engine/test_utils.h"
#include "update_engine/update_metadata.pb.h"
#include "update_engine/utils.h"

// This file contains a simple program that unpacks a delta diff into a
// directory.

using std::set;
using std::string;
using std::vector;
using std::tr1::shared_ptr;

DEFINE_string(delta, "", "the delta file");
DEFINE_string(output_dev, "", "the output device");
DEFINE_string(root, "", "the fake system root");
DEFINE_string(dump_delta, "", "path to delta file to dump");

namespace chromeos_update_engine {

class TestInstaller : public ActionProcessorDelegate {
 public:
  TestInstaller(GMainLoop *loop,
                const string& sys_root,
                const string& delta_path,
                const string& install_path)
      : loop_(loop),
        sys_root_(sys_root),
        install_path_(install_path) {}
  void Update();

  // Delegate method:
  void ProcessingDone(const ActionProcessor* processor, bool success);
 private:
  vector<shared_ptr<AbstractAction> > actions_;
  ActionProcessor processor_;
  GMainLoop *loop_;
  string sys_root_;
  string install_path_;
};

// Returns true on success. If there was no update available, that's still
// success.
// If force_full is true, try to force a full update.
void TestInstaller::Update() {
  CHECK(!processor_.IsRunning());
  processor_.set_delegate(this);

  // Actions:
  shared_ptr<ObjectFeederAction<InstallPlan> > object_feeder_action(
      new ObjectFeederAction<InstallPlan>);
  shared_ptr<FilesystemCopierAction> filesystem_copier_action(
      new FilesystemCopierAction);
  // shared_ptr<InstallAction> install_action(  // re-add
  //     new InstallAction);

  actions_.push_back(object_feeder_action);
  actions_.push_back(filesystem_copier_action);
  // actions_.push_back(install_action);  // re-add

  // Enqueue the actions
  for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
       it != actions_.end(); ++it) {
    processor_.EnqueueAction(it->get());
  }

  // Bond them together. We have to use the leaf-types when calling
  // BondActions().
  BondActions(object_feeder_action.get(), filesystem_copier_action.get());
  // re-add
  // BondActions(filesystem_copier_action.get(), install_action.get());
  
  InstallPlan install_plan(false,
                           "",
                           "",
                           install_path_);
  filesystem_copier_action->set_copy_source(sys_root_);
  object_feeder_action->set_obj(install_plan);
  processor_.StartProcessing();
}

void TestInstaller::ProcessingDone(const ActionProcessor* processor,
                                   bool success) {
  LOG(INFO) << "install " << (success ? "succeeded" : "failed");
  actions_.clear();
  g_main_loop_quit(loop_);
}

gboolean TestInstallInMainLoop(void* arg) {
  TestInstaller* test_installer = reinterpret_cast<TestInstaller*>(arg);
  test_installer->Update();
  return FALSE;  // Don't call this callback function again
}


void usage(const char* argv0) {
  printf("usage: %s --root=system_root --delta=delta_file "
         "--output_dev=output_dev\n", argv0);
  exit(1);
}

bool Main(int argc, char** argv) {
  g_thread_init(NULL);
  google::ParseCommandLineFlags(&argc, &argv, true);
  logging::InitLogging("",
                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
                       logging::DONT_LOCK_LOG_FILE,
                       logging::APPEND_TO_OLD_LOG_FILE);

  LOG(INFO) << "starting";
  
  // Create the single GMainLoop
  GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);

  chromeos_update_engine::TestInstaller test_installer(loop,
                                                       FLAGS_root,
                                                       FLAGS_delta,
                                                       FLAGS_output_dev);

  g_timeout_add(0, &chromeos_update_engine::TestInstallInMainLoop,
                &test_installer);

  g_main_loop_run(loop);
  g_main_loop_unref(loop);

  LOG(INFO) << "Done.";
  return true;
}

}  // namespace chromeos_update_engine

int main(int argc, char** argv) {
  return chromeos_update_engine::Main(argc, argv) ? 0 : 1;
}
