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

#include "services/dart/dart_app.h"

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/trace_event/trace_event.h"
#include "mojo/dart/embedder/dart_controller.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
#include "mojo/data_pipe_utils/data_pipe_utils.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/zlib/google/zip_reader.h"
#include "url/gurl.h"

using mojo::Application;

namespace dart {

DartApp::DartApp(mojo::InterfaceRequest<Application> application_request,
                 const std::string& base_uri,
                 const base::FilePath& application_dir,
                 bool strict,
                 bool run_on_message_loop)
    : application_request_(application_request.Pass()),
      application_dir_(application_dir),
      main_isolate_(nullptr) {
  base::FilePath snapshot_path = application_dir_.Append("snapshot_blob.bin");
  config_.base_uri = base_uri;
  config_.use_dart_run_loop = !run_on_message_loop;
  // Look for snapshot_blob.bin. If exists, then load from snapshot.
  if (base::PathExists(snapshot_path)) {
    config_.script_uri = snapshot_path.AsUTF8Unsafe();
    config_.package_root = "";
  } else {
    LOG(ERROR) << "Dart entry point could not be found under: "
               << application_dir_.AsUTF8Unsafe();
    base::MessageLoop::current()->QuitWhenIdle();
  }

  config_.application_data = reinterpret_cast<void*>(this);
  config_.strict_compilation = strict;
  config_.SetVmFlags(nullptr, 0);

  base::MessageLoop::current()->PostTask(FROM_HERE,
      base::Bind(&DartApp::OnAppLoaded, base::Unretained(this)));
}

// Assume that |url| ends in a file name in lib/, and as a peer to lib/
// is the packages directory.
// 1) Strip the filename.
// 2) Strip lib/
// 3) Append with packages/.
// 4) Reconstruct full url.
static std::string SimplePackageRootFromUrl(std::string url) {
  GURL gurl = GURL(url);
  base::FilePath path = base::FilePath(gurl.path());
  path = path.DirName();
  path = path.DirName();
  path = path.Append("packages");
  path = path.AsEndingWithSeparator();
  const std::string& path_string = path.value();
  GURL::Replacements path_replacement;
  path_replacement.SetPath(path_string.data(),
                           url::Component(0, path_string.size()));
  gurl = gurl.ReplaceComponents(path_replacement);
  return gurl.spec();
}

// Returns the path component from |url|.
static std::string ExtractPath(std::string url) {
  GURL gurl = GURL(url);
  return gurl.path();
}

static bool IsFileScheme(std::string url) {
  GURL gurl = GURL(url);
  return gurl.SchemeIsFile();
}

DartApp::DartApp(mojo::InterfaceRequest<Application> application_request,
                 const std::string& url,
                 bool strict,
                 bool run_on_message_loop)
    : application_request_(application_request.Pass()),
      main_isolate_(nullptr) {
  config_.application_data = reinterpret_cast<void*>(this);
  config_.strict_compilation = strict;
  config_.base_uri = url;
  config_.use_dart_run_loop = !run_on_message_loop;
  if (IsFileScheme(url)) {
    // Strip file:// and use the path directly.
    config_.script_uri = ExtractPath(url);
    config_.package_root = ExtractPath(SimplePackageRootFromUrl(url));
    config_.use_network_loader = false;
  } else {
    // Use the full url.
    config_.script_uri = url;
    config_.package_root = SimplePackageRootFromUrl(url);
    config_.use_network_loader = true;
  }
  config_.SetVmFlags(nullptr, 0);

  base::MessageLoop::current()->PostTask(FROM_HERE,
      base::Bind(&DartApp::OnAppLoaded, base::Unretained(this)));
}

DartApp::~DartApp() {
  if (main_isolate_ != nullptr) {
    mojo::dart::DartController::ShutdownIsolate(main_isolate_);
    main_isolate_ = nullptr;
  }
}

void DartApp::OnAppLoaded() {
  char* error = nullptr;
  config_.handle = application_request_.PassMessagePipe().release().value();
  config_.error = &error;
  main_isolate_ = mojo::dart::DartController::StartupIsolate(config_);
  if (!main_isolate_) {
    LOG(ERROR) << error;
    free(error);
  }
  if (config_.use_dart_run_loop) {
    // let TraceLog know about that RunToCompletion blocks the message loop.
    auto trace_log = base::trace_event::TraceLog::GetInstance();
    trace_log->SetCurrentThreadBlocksMessageLoop();
    mojo::dart::DartController::RunToCompletion(main_isolate_);
    base::MessageLoop::current()->QuitWhenIdle();
  }
}

}  // namespace dart
