/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/base/task.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/taskrunner.h"

namespace rtc {

int32_t Task::unique_id_seed_ = 0;

Task::Task(TaskParent *parent)
    : TaskParent(this, parent),
      state_(STATE_INIT),
      blocked_(false),
      done_(false),
      aborted_(false),
      busy_(false),
      error_(false),
      start_time_(0),
      timeout_time_(0),
      timeout_seconds_(0),
      timeout_suspended_(false)  {
  unique_id_ = unique_id_seed_++;

  // sanity check that we didn't roll-over our id seed
  RTC_DCHECK(unique_id_ < unique_id_seed_);
}

Task::~Task() {
  // Is this task being deleted in the correct manner?
#if RTC_DCHECK_IS_ON
  RTC_DCHECK(!done_ || GetRunner()->is_ok_to_delete(this));
#endif
  RTC_DCHECK(state_ == STATE_INIT || done_);
  RTC_DCHECK(state_ == STATE_INIT || blocked_);

  // If the task is being deleted without being done, it
  // means that it hasn't been removed from its parent.
  // This happens if a task is deleted outside of TaskRunner.
  if (!done_) {
    Stop();
  }
}

int64_t Task::CurrentTime() {
  return GetRunner()->CurrentTime();
}

int64_t Task::ElapsedTime() {
  return CurrentTime() - start_time_;
}

void Task::Start() {
  if (state_ != STATE_INIT)
    return;
  // Set the start time before starting the task.  Otherwise if the task
  // finishes quickly and deletes the Task object, setting start_time_
  // will crash.
  start_time_ = CurrentTime();
  GetRunner()->StartTask(this);
}

void Task::Step() {
  if (done_) {
#if RTC_DCHECK_IS_ON
    // we do not know how !blocked_ happens when done_ - should be impossible.
    // But it causes problems, so in retail build, we force blocked_, and
    // under debug we assert.
    RTC_DCHECK(blocked_);
#else
    blocked_ = true;
#endif
    return;
  }

  // Async Error() was called
  if (error_) {
    done_ = true;
    state_ = STATE_ERROR;
    blocked_ = true;
//   obsolete - an errored task is not considered done now
//   SignalDone();

    Stop();
#if RTC_DCHECK_IS_ON
    // verify that stop removed this from its parent
    RTC_DCHECK(!parent()->IsChildTask(this));
#endif
    return;
  }

  busy_ = true;
  int new_state = Process(state_);
  busy_ = false;

  if (aborted_) {
    Abort(true);  // no need to wake because we're awake
    return;
  }

  if (new_state == STATE_BLOCKED) {
    blocked_ = true;
    // Let the timeout continue
  } else {
    state_ = new_state;
    blocked_ = false;
    ResetTimeout();
  }

  if (new_state == STATE_DONE) {
    done_ = true;
  } else if (new_state == STATE_ERROR) {
    done_ = true;
    error_ = true;
  }

  if (done_) {
//  obsolete - call this yourself
//    SignalDone();

    Stop();
#if RTC_DCHECK_IS_ON
    // verify that stop removed this from its parent
    RTC_DCHECK(!parent()->IsChildTask(this));
#endif
    blocked_ = true;
  }
}

void Task::Abort(bool nowake) {
  // Why only check for done_ (instead of "aborted_ || done_")?
  //
  // If aborted_ && !done_, it means the logic for aborting still
  // needs to be executed (because busy_ must have been true when
  // Abort() was previously called).
  if (done_)
    return;
  aborted_ = true;
  if (!busy_) {
    done_ = true;
    blocked_ = true;
    error_ = true;

    // "done_" is set before calling "Stop()" to ensure that this code 
    // doesn't execute more than once (recursively) for the same task.
    Stop();
#if RTC_DCHECK_IS_ON
    // verify that stop removed this from its parent
    RTC_DCHECK(!parent()->IsChildTask(this));
#endif
    if (!nowake) {
      // WakeTasks to self-delete.
      // Don't call Wake() because it is a no-op after "done_" is set.
      // Even if Wake() did run, it clears "blocked_" which isn't desireable.
      GetRunner()->WakeTasks();
    }
  }
}

void Task::Wake() {
  if (done_)
    return;
  if (blocked_) {
    blocked_ = false;
    GetRunner()->WakeTasks();
  }
}

void Task::Error() {
  if (error_ || done_)
    return;
  error_ = true;
  Wake();
}

std::string Task::GetStateName(int state) const {
  switch (state) {
    case STATE_BLOCKED: return "BLOCKED";
    case STATE_INIT: return "INIT";
    case STATE_START: return "START";
    case STATE_DONE: return "DONE";
    case STATE_ERROR: return "ERROR";
    case STATE_RESPONSE: return "RESPONSE";
  }
  return "??";
}

int Task::Process(int state) {
  int newstate = STATE_ERROR;

  if (TimedOut()) {
    ClearTimeout();
    newstate = OnTimeout();
    SignalTimeout();
  } else {
    switch (state) {
      case STATE_INIT:
        newstate = STATE_START;
        break;
      case STATE_START:
        newstate = ProcessStart();
        break;
      case STATE_RESPONSE:
        newstate = ProcessResponse();
        break;
      case STATE_DONE:
      case STATE_ERROR:
        newstate = STATE_BLOCKED;
        break;
    }
  }

  return newstate;
}

void Task::Stop() {
  // No need to wake because we're either awake or in abort
  TaskParent::OnStopped(this);
}

int Task::ProcessResponse() {
  return STATE_DONE;
}

void Task::set_timeout_seconds(const int timeout_seconds) {
  timeout_seconds_ = timeout_seconds;
  ResetTimeout();
}

bool Task::TimedOut() {
  return timeout_seconds_ &&
    timeout_time_ &&
    CurrentTime() >= timeout_time_;
}

void Task::ResetTimeout() {
  int64_t previous_timeout_time = timeout_time_;
  bool timeout_allowed = (state_ != STATE_INIT)
                      && (state_ != STATE_DONE)
                      && (state_ != STATE_ERROR);
  if (timeout_seconds_ && timeout_allowed && !timeout_suspended_)
    timeout_time_ = CurrentTime() +
                    (timeout_seconds_ * kSecToMsec * kMsecTo100ns);
  else
    timeout_time_ = 0;

  GetRunner()->UpdateTaskTimeout(this, previous_timeout_time);
}

void Task::ClearTimeout() {
  int64_t previous_timeout_time = timeout_time_;
  timeout_time_ = 0;
  GetRunner()->UpdateTaskTimeout(this, previous_timeout_time);
}

void Task::SuspendTimeout() {
  if (!timeout_suspended_) {
    timeout_suspended_ = true;
    ResetTimeout();
  }
}

void Task::ResumeTimeout() {
  if (timeout_suspended_) {
    timeout_suspended_ = false;
    ResetTimeout();
  }
}

int Task::OnTimeout() {
  // by default, we are finished after timing out
  return STATE_DONE;
}

} // namespace rtc
