// Copyright (c) 2011 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 "chrome/browser/printing/print_job.h"

#include "base/message_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer.h"
#include "chrome/browser/printing/print_job_worker.h"
#include "content/common/notification_service.h"
#include "printing/printed_document.h"
#include "printing/printed_page.h"

using base::TimeDelta;

namespace printing {

PrintJob::PrintJob()
    : ui_message_loop_(MessageLoop::current()),
      source_(NULL),
      worker_(),
      settings_(),
      is_job_pending_(false),
      is_canceling_(false) {
  DCHECK(ui_message_loop_);
  // This is normally a UI message loop, but in unit tests, the message loop is
  // of the 'default' type.
  DCHECK(ui_message_loop_->type() == MessageLoop::TYPE_UI ||
         ui_message_loop_->type() == MessageLoop::TYPE_DEFAULT);
  ui_message_loop_->AddDestructionObserver(this);
}

PrintJob::~PrintJob() {
  ui_message_loop_->RemoveDestructionObserver(this);
  // The job should be finished (or at least canceled) when it is destroyed.
  DCHECK(!is_job_pending_);
  DCHECK(!is_canceling_);
  if (worker_.get())
    DCHECK(worker_->message_loop() == NULL);
  DCHECK_EQ(ui_message_loop_, MessageLoop::current());
}

void PrintJob::Initialize(PrintJobWorkerOwner* job,
                          PrintedPagesSource* source,
                          int page_count) {
  DCHECK(!source_);
  DCHECK(!worker_.get());
  DCHECK(!is_job_pending_);
  DCHECK(!is_canceling_);
  DCHECK(!document_.get());
  source_ = source;
  worker_.reset(job->DetachWorker(this));
  settings_ = job->settings();

  PrintedDocument* new_doc =
      new PrintedDocument(settings_, source_, job->cookie());
  new_doc->set_page_count(page_count);
  UpdatePrintedDocument(new_doc);

  // Don't forget to register to our own messages.
  registrar_.Add(this, NotificationType::PRINT_JOB_EVENT,
                 Source<PrintJob>(this));
}

void PrintJob::Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
  DCHECK_EQ(ui_message_loop_, MessageLoop::current());
  switch (type.value) {
    case NotificationType::PRINT_JOB_EVENT: {
      OnNotifyPrintJobEvent(*Details<JobEventDetails>(details).ptr());
      break;
    }
    default: {
      break;
    }
  }
}

void PrintJob::GetSettingsDone(const PrintSettings& new_settings,
                               PrintingContext::Result result) {
  NOTREACHED();
}

PrintJobWorker* PrintJob::DetachWorker(PrintJobWorkerOwner* new_owner) {
  NOTREACHED();
  return NULL;
}

MessageLoop* PrintJob::message_loop() {
  return ui_message_loop_;
}

const PrintSettings& PrintJob::settings() const {
  return settings_;
}

int PrintJob::cookie() const {
  if (!document_.get())
    // Always use an invalid cookie in this case.
    return 0;
  return document_->cookie();
}

void PrintJob::WillDestroyCurrentMessageLoop() {
  NOTREACHED();
}

void PrintJob::StartPrinting() {
  DCHECK_EQ(ui_message_loop_, MessageLoop::current());
  DCHECK(worker_->message_loop());
  DCHECK(!is_job_pending_);
  if (!worker_->message_loop() || is_job_pending_)
    return;

  // Real work is done in PrintJobWorker::StartPrinting().
  worker_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
      worker_.get(), &PrintJobWorker::StartPrinting, document_));
  // Set the flag right now.
  is_job_pending_ = true;

  // Tell everyone!
  scoped_refptr<JobEventDetails> details(
      new JobEventDetails(JobEventDetails::NEW_DOC, document_.get(), NULL));
  NotificationService::current()->Notify(
      NotificationType::PRINT_JOB_EVENT,
      Source<PrintJob>(this),
      Details<JobEventDetails>(details.get()));
}

void PrintJob::Stop() {
  DCHECK_EQ(ui_message_loop_, MessageLoop::current());

  // Be sure to live long enough.
  scoped_refptr<PrintJob> handle(this);

  MessageLoop* worker_loop = worker_->message_loop();
  if (worker_loop) {
    ControlledWorkerShutdown();

    is_job_pending_ = false;
    registrar_.Remove(this, NotificationType::PRINT_JOB_EVENT,
                      Source<PrintJob>(this));
  }
  // Flush the cached document.
  UpdatePrintedDocument(NULL);
}

void PrintJob::Cancel() {
  if (is_canceling_)
    return;
  is_canceling_ = true;

  // Be sure to live long enough.
  scoped_refptr<PrintJob> handle(this);

  DCHECK_EQ(ui_message_loop_, MessageLoop::current());
  MessageLoop* worker_loop = worker_.get() ? worker_->message_loop() : NULL;
  if (worker_loop) {
    // Call this right now so it renders the context invalid. Do not use
    // InvokeLater since it would take too much time.
    worker_->Cancel();
  }
  // Make sure a Cancel() is broadcast.
  scoped_refptr<JobEventDetails> details(
      new JobEventDetails(JobEventDetails::FAILED, NULL, NULL));
  NotificationService::current()->Notify(
      NotificationType::PRINT_JOB_EVENT,
      Source<PrintJob>(this),
      Details<JobEventDetails>(details.get()));
  Stop();
  is_canceling_ = false;
}

bool PrintJob::FlushJob(int timeout_ms) {
  // Make sure the object outlive this message loop.
  scoped_refptr<PrintJob> handle(this);

  // Stop() will eventually be called, which will get out of the inner message
  // loop. But, don't take it for granted and set a timer in case something goes
  // wrong.
  base::OneShotTimer<MessageLoop> quit_task;
  if (timeout_ms) {
    quit_task.Start(TimeDelta::FromMilliseconds(timeout_ms),
                    MessageLoop::current(), &MessageLoop::Quit);
  }

  bool old_state = MessageLoop::current()->NestableTasksAllowed();
  MessageLoop::current()->SetNestableTasksAllowed(true);
  MessageLoop::current()->Run();
  // Restore task state.
  MessageLoop::current()->SetNestableTasksAllowed(old_state);

  return true;
}

void PrintJob::DisconnectSource() {
  source_ = NULL;
  if (document_.get())
    document_->DisconnectSource();
}

bool PrintJob::is_job_pending() const {
  return is_job_pending_;
}

PrintedDocument* PrintJob::document() const {
  return document_.get();
}

void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
  if (document_.get() == new_document)
    return;

  document_ = new_document;

  if (document_.get()) {
    settings_ = document_->settings();
  }

  if (worker_.get() && worker_->message_loop()) {
    DCHECK(!is_job_pending_);
    // Sync the document with the worker.
    worker_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
        worker_.get(), &PrintJobWorker::OnDocumentChanged, document_));
  }
}

void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
  switch (event_details.type()) {
    case JobEventDetails::FAILED: {
      settings_.Clear();
      // No need to cancel since the worker already canceled itself.
      Stop();
      break;
    }
    case JobEventDetails::USER_INIT_DONE:
    case JobEventDetails::DEFAULT_INIT_DONE:
    case JobEventDetails::USER_INIT_CANCELED: {
      DCHECK_EQ(event_details.document(), document_.get());
      break;
    }
    case JobEventDetails::NEW_DOC:
    case JobEventDetails::NEW_PAGE:
    case JobEventDetails::PAGE_DONE:
    case JobEventDetails::JOB_DONE:
    case JobEventDetails::ALL_PAGES_REQUESTED: {
      // Don't care.
      break;
    }
    case JobEventDetails::DOC_DONE: {
      // This will call Stop() and broadcast a JOB_DONE message.
      MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
          this, &PrintJob::OnDocumentDone));
      break;
    }
    default: {
      NOTREACHED();
      break;
    }
  }
}

void PrintJob::OnDocumentDone() {
  // Be sure to live long enough. The instance could be destroyed by the
  // JOB_DONE broadcast.
  scoped_refptr<PrintJob> handle(this);

  // Stop the worker thread.
  Stop();

  scoped_refptr<JobEventDetails> details(
      new JobEventDetails(JobEventDetails::JOB_DONE, document_.get(), NULL));
  NotificationService::current()->Notify(
      NotificationType::PRINT_JOB_EVENT,
      Source<PrintJob>(this),
      Details<JobEventDetails>(details.get()));
}

void PrintJob::ControlledWorkerShutdown() {
  DCHECK_EQ(ui_message_loop_, MessageLoop::current());

  // The deadlock this code works around is specific to window messaging on
  // Windows, so we aren't likely to need it on any other platforms.
#if defined(OS_WIN)
  // We could easily get into a deadlock case if worker_->Stop() is used; the
  // printer driver created a window as a child of the browser window. By
  // canceling the job, the printer driver initiated dialog box is destroyed,
  // which sends a blocking message to its parent window. If the browser window
  // thread is not processing messages, a deadlock occurs.
  //
  // This function ensures that the dialog box will be destroyed in a timely
  // manner by the mere fact that the thread will terminate. So the potential
  // deadlock is eliminated.
  worker_->StopSoon();

  // Run a tight message loop until the worker terminates. It may seems like a
  // hack but I see no other way to get it to work flawlessly. The issues here
  // are:
  // - We don't want to run tasks while the thread is quitting.
  // - We want this code path to wait on the thread to quit before continuing.
  MSG msg;
  HANDLE thread_handle = worker_->thread_handle();
  for (; thread_handle;) {
    // Note that we don't do any kind of message priorization since we don't
    // execute any pending task or timer.
    DWORD result = MsgWaitForMultipleObjects(1, &thread_handle,
                                             FALSE, INFINITE, QS_ALLINPUT);
    if (result == WAIT_OBJECT_0 + 1) {
      while (PeekMessage(&msg, NULL, 0, 0, TRUE) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
      }
      // Continue looping.
    } else if (result == WAIT_OBJECT_0) {
      // The thread quit.
      break;
    } else {
      // An error occured. Assume the thread quit.
      NOTREACHED();
      break;
    }
  }
#endif

  // Temporarily allow it until we fix
  // http://code.google.com/p/chromium/issues/detail?id=67044
  base::ThreadRestrictions::ScopedAllowIO allow_io;

  // Now make sure the thread object is cleaned up.
  worker_->Stop();
}

// Takes settings_ ownership and will be deleted in the receiving thread.
JobEventDetails::JobEventDetails(Type type,
                                 PrintedDocument* document,
                                 PrintedPage* page)
    : document_(document),
      page_(page),
      type_(type) {
}

JobEventDetails::~JobEventDetails() {
}

PrintedDocument* JobEventDetails::document() const {
  return document_;
}

PrintedPage* JobEventDetails::page() const {
  return page_;
}

}  // namespace printing
