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

#ifndef STARBOARD_COMMON_STATE_MACHINE_H_
#define STARBOARD_COMMON_STATE_MACHINE_H_

#include <queue>
#include <string>

#include "starboard/common/optional.h"
#include "starboard/configuration.h"
#include "starboard/export.h"

namespace starboard {

// An approximate implementation of a run-to-completion (RTC) Hierarchical State
// Machine (HSM), supporting most UML Statechart semantics.
//
// Some good background information on UML Statecharts, mostly written by Miro
// Samek:
// http://en.wikipedia.org/wiki/UML_state_machine
//
// And Miro Samek's 3-part article on practical UML Statecharts:
// http://www.embedded.com/design/prototyping-and-development/4008247/A-crash-course-in-UML-state-machines-Part-1
//
// This class does not provide any intrinsic support for "orthogonal regions,"
// "extended state," or "deferred events." "Guard conditions" are easily
// implemented by the client directly in the event handler. It also minorly
// deviates from the UML Statechart specification by calling transition handlers
// before exiting the current states. This is because this implementation uses a
// simplification which combines the transition handlers and the
// state-event-transition map into a single function (HandleUserStateEvent).
//
// This class is not thread-safe. It is the user's responsibility to synchronize
// calls into the state machine, either with locks or by simply using from a
// single thread.
//
// Terse suggestions for using this class:
//   * Use the templated StateMachine wrapper class instead of this class
//     directly.
//   * Define two enums, one for your states, and one for your events.
//   * Subclass to define your state machine and event handlers.
//   * Avoid directly exposing or passing around state machines (wrap instead).
//     Handle() is not a great public interface.
//   * Include your state machine in another class as a private by-value member.
//   * Synchronize access to the state machine.
//   * Prefer writing state machine event handlers over checking if the machine
//     IsIn() a particular state.
//   * Convert public methods into events, get into the state machine as quickly
//     as possible.
//   * You only need to define a state when you are going to leave the state
//     machine in a particular condition where events can occur.
//   * Create a superstate when you have an event you want to handle the same
//     way for a collection of states.
//   * When managing resources, create a state or superstate that represents the
//     acquisition of that resource, and release the resource in the Exit
//     handler.
//
// Some Definitions:
//   Simple State      - A State with no substates. The state machine is always
//                       left in exactly one Simple State.
//   Composite State   - A State with at least one substate.
//   Guard Condition   - An external condition on which an event handler
//                       branches.
//   Run-To-Completion - A property specifying that the state machine handles
//                       one event at a time, and no events are handled until
//                       the previous event is done being handled.
//
// See the unittests for this class for a contrived example state machine
// implementation.
class StateMachineBase {
 public:
  // --- Nested Types and Constants ---

  typedef uint32_t State;
  typedef uint32_t Event;

  // --- Public Methods ---

  // Constructor with name. The name is helpful for debugging.
  explicit StateMachineBase(const std::string& name);
  virtual ~StateMachineBase() {}

  // Enters the initial state, as specified by |GetUserInitialState()| and
  // follows the initial substates down to the first simple (childless) state
  // found. Idempotent. Will happen automatically on the first |Handle()| call,
  // if not done explicitly.
  void Initialize();

  // Gets the name of this state machine, for logging purposes.
  const char* name() const { return name_.c_str(); }

  // Gets a version number that increases monotonically with each state
  // transition (unless it overflows |uint64_t|). This can be useful for timers
  // and asynchronous events that only want to do their action if the state has
  // not changed since they were queued.
  //
  // The state version changes exactly once per transition. In other words, it
  // doesn't change for every Enter and Exit for a transition.
  uint64_t version() const { return version_; }

  // Gets the simplest current state that this state machine is in. To check if
  // the state machine is in a particular composite state, use |IsIn()|. Returns
  // null if uninitialized.
  optional<State> state() const { return state_; }

  // Reports whether the state machine is currently in the given state. A state
  // machine is considered to be "in" the current simple state, but also "in"
  // all superstates of the current simple state.
  bool IsIn(State state) const;

  // Gets a printable string for the given state.
  const char* GetStateString(optional<State> state) const;

  // Gets a printable string for the given event.
  const char* GetEventString(optional<Event> event) const;

  // Handles the given event in the context of the state machine's current
  // state, executing the appropriate event handlers and performing any
  // precipitate state transitions. If called reentrantly, the event will be
  // queued until the current event has run to completion.
  //
  // |data| is a way to pass auxiliary data to the event handler. No retention
  // or ref-counting is done on that data, it is simply passed through to the
  // event handler. Since |Handle()| will queue the event if (and only if)
  // called from an event handler, it is up to the caller to ensure the lifetime
  // of whatever is passed in here.
  void Handle(Event event, void* data = NULL);

 protected:
  // --- Protected Nested Types ---

  // A type that can be returned from a state-event handler, which will be
  // coerced into the appropriate Result structure.
  enum HandledState {
    // The event handler returns this to say that the handler consume the event,
    // but caused no state transition.
    kHandled,

    // The event handler returns this to say that the handler did not consume
    // the event, and it should bubble up to the parent state, if any.
    kNotHandled,
  };

  // Structure that handlers return, allowing them to cause state transitions or
  // prevent the event from bubbling. State-event handlers may just return a
  // HandledState or a state to transition to, and it will be coerced into this
  // structure.
  struct Result {
    // Default constructor is unhandled.
    Result() : is_transition(false), is_external(false), is_handled(false) {}

    // The no-transition constructor. Non-explicit so that the implementor of
    // |HandleUserStateEvent()| just needs to return a |HandledState| and it
    // does the right thing.
    Result(HandledState handled)  // NOLINT(runtime/explicit)
        : is_transition(false),
          is_external(false),
          is_handled(handled == kHandled) {}

    // The state transition constructor. This implies that the event was
    // handled. Non-explicit so that the implementor of |HandleUserStateEvent()|
    // just needs to return a State and it does a non-external transition.
    Result(State transition_target,
           bool external = false)  // NOLINT(runtime/explicit)
        : target(transition_target),
          is_transition(true),
          is_external(external),
          is_handled(true) {}

    Result& operator=(HandledState rhs) {
      target = nullopt;
      is_transition = false;
      is_external = false;
      is_handled = (rhs == kHandled);
      return *this;
    }

    Result& operator=(State transition_target) {
      target = transition_target;
      is_transition = true;
      is_external = false;
      is_handled = true;
      return *this;
    }

    // State to transition to. Only valid if is_transition is true.
    optional<State> target;

    // Whether this result indicates a state transition.
    bool is_transition;

    // Whether the specified transition is external. Only meaningful if
    // is_transition is true.
    //
    // For more on state transitions, see:
    // http://en.wikipedia.org/wiki/UML_state_machine#Transition_execution_sequence
    bool is_external;

    // Whether the event was handled by the handler. If true, consumes the
    // event, and prevents bubbling up to superstates. False propagates the
    // event to superstates.
    bool is_handled;
  };

  struct EventWithData {
    EventWithData(Event event, void* data) : event(event), data(data) {}
    Event event;
    void* data;
  };

  // --- Implementation Interface for Subclasses ---

  // Abstract method for subclasses to define the state hierarchy. It is
  // recommended that all user-defined states be descendents of a single "top"
  // state.
  virtual optional<State> GetUserParentState(State state) const = 0;

  // Abstract method for subclasses to define the initial substate of their
  // states, which is required for all complex states. If a state is a simple
  // state (no substates), returns null.
  virtual optional<State> GetUserInitialSubstate(State state) const = 0;

  // Abstract method for subclasses to define the initial (top) state of their
  // state machine. This must be a state that has no parent. This state will be
  // entered upon calling |Initialize()|.
  virtual State GetUserInitialState() const = 0;

  // Optional method for subclasses to define strings for their states, solely
  // used for debugging purposes.
  virtual const char* GetUserStateString(State state) const { return NULL; }

  // Optional method for subclasses to define strings for their events, solely
  // used for debugging purposes.
  virtual const char* GetUserEventString(Event event) const { return NULL; }

  // Abstract method for subclasses to define handlers for events in given
  // states. This method must return either:
  //   a) a state to transition to, meaning the event was handled and caused
  //      a transition
  //   b) |kHandled| meaning the event was handled but no transition occurred
  //   c) |kNotHandled|, meaning the event should bubble up to the parent state
  //   d) an explicit Result structure, mainly for external transitions.
  //
  // Implementations wishing to catch all unhandled events may do so in their
  // top state.
  //
  // This method is generally implemented as a nested switch statement, with the
  // outer switch on |state| and the inner switch on |event|. You may want to
  // break this apart into per-state or per-state-event functions for
  // readability and maintainability.
  virtual Result HandleUserStateEvent(State state, Event event, void* data) = 0;

  // Abstract method for subclasses to define state entry behaviors.
  virtual void HandleUserStateEnter(State state) = 0;

  // Abstract method for subclasses to define state exit behaviors.
  virtual void HandleUserStateExit(State state) = 0;

  // --- Helper Methods for Subclasses ---

  // Subclasses can call this method to turn on logging. Logging is opt-in,
  // because it can be very verbose, and is likely only useful during
  // development of a particular state machine.
  void EnableLogging() { should_log_ = true; }

 private:
  // --- Private Helper Methods ---

  // Gets the parent state of the given state.
  optional<State> GetParentState(optional<State> state) const;

  // Gets the initial substate of given state.
  optional<State> GetInitialSubstate(optional<State> state) const;

  // Handles all queued events until there are no more to run. Event handlers
  // may queue more events by calling |Handle()|, and this method will also
  // process all precipitate events.
  void HandleQueuedEvents();

  // Workhorse method for handling a single event.
  void HandleOneEvent(Event event, void* data);

  // Gets the path from the Top state to the given |state|, storing it in the
  // given |out_path| array, up to |max_depth| entries. If specified,
  // |out_depth| will be set to the number of valid states that fit in the given
  // array.
  void GetPath(State state,
               size_t max_depth,
               State* out_path,
               size_t* out_depth) const;

  // Transitions between the given source and target states, assuming that the
  // source state is in the current state path to the Top state. The source
  // state is the state whose handler generated the transition.
  //
  // See:
  // http://en.wikipedia.org/wiki/UML_state_machine#Transition_execution_sequence
  void Transition(Event event, State source, State target, bool is_external);

  // Follows the initial substates from the current state until it reaches a
  // simple state.
  void FollowInitialSubstates();

  // Enters the given state.
  void EnterState(State state);

  // Exits the current state to its parent.
  void ExitCurrentState();

  // --- Members ---

  // The name of this state machine, for debugging purposes.
  const std::string name_;

  // The current state of this state machine. Null until initialized.
  optional<State> state_;

  // The unique version of this state machine's state, updated on every
  // transition.
  uint64_t version_;

  // Queue of events to handle once the current event is done being
  // handled. Should always be empty unless |is_handling_| is true.
  std::queue<EventWithData> event_queue_;

  // Whether this state machine is actively handling an event. Used to detect
  // reentrant calls to |Handle()|.
  bool is_handling_;

  // Whether the state machine has been initialized into its initial state
  // yet. Used to make |Initialize()| idempotent.
  bool is_initialized_;

  // Whether the state machine should log information about state transitions.
  bool should_log_;
};

// A convenience template wrapper for StateMachineBase. See the above class
// for complete documentation. Basically, you define your states and events as
// two enums, and then pass them as template args to this template class. Your
// state machine should then subclass this template class. It then does the work
// of casting and converting back and forth from your enums to
// StateMachineBase's numeric State and Event definitions.
//
// All the methods in this class, protected and public, match the description
// and behavioral contracts of the equivalently named method in
// StateMachineBase.
template <typename StateEnum, typename EventEnum>
class StateMachine {
 public:
  // --- Nested Types and Constants ---

  explicit StateMachine(const std::string& name) : machine_(this, name) {}
  virtual ~StateMachine() {}

  void Initialize() { machine_.Initialize(); }

  const char* name() const { return machine_.name(); }

  uint64_t version() const { return machine_.version(); }

  optional<StateEnum> state() const {
    optional<BaseState> wrappedState = machine_.state();
    return (wrappedState ? static_cast<StateEnum>(*wrappedState)
                         : optional<StateEnum>());
  }

  bool IsIn(StateEnum state) const {
    return machine_.IsIn(static_cast<BaseState>(state));
  }

  const char* GetStateString(optional<StateEnum> state) const {
    return machine_.GetStateString(state ? static_cast<BaseState>(*state)
                                         : optional<BaseState>());
  }

  const char* GetEventString(optional<EventEnum> event) const {
    return machine_.GetEventString(event ? static_cast<BaseEvent>(*event)
                                         : optional<BaseEvent>());
  }

  void Handle(EventEnum event, void* data = NULL) {
    machine_.Handle(static_cast<BaseEvent>(event), data);
  }

 protected:
  // See the other HandledState in StateMachineBase.
  enum HandledState {
    kHandled,
    kNotHandled,
  };

  // See the other Result in StateMachineBase.
  struct Result {
    Result(HandledState handled)  // NOLINT(runtime/explicit)
        : target(),
          is_transition(false),
          is_external(false),
          is_handled(handled == kHandled) {}

    Result(StateEnum transition_target,
           bool external = false)  // NOLINT(runtime/explicit)
        : target(transition_target),
          is_transition(true),
          is_external(external),
          is_handled(true) {}

    Result& operator=(HandledState rhs) {
      target = nullopt;
      is_transition = false;
      is_external = false;
      is_handled = (rhs == kHandled);
      return *this;
    }

    Result& operator=(StateEnum transition_target) {
      target = transition_target;
      is_transition = true;
      is_external = false;
      is_handled = true;
      return *this;
    }

    optional<StateEnum> target;
    bool is_transition;
    bool is_external;
    bool is_handled;
  };

  virtual optional<StateEnum> GetUserParentState(StateEnum state) const = 0;
  virtual optional<StateEnum> GetUserInitialSubstate(StateEnum state) const = 0;
  virtual StateEnum GetUserInitialState() const = 0;
  virtual const char* GetUserStateString(StateEnum state) const { return NULL; }
  virtual const char* GetUserEventString(EventEnum event) const { return NULL; }
  virtual Result HandleUserStateEvent(StateEnum state,
                                      EventEnum event,
                                      void* data) = 0;
  virtual void HandleUserStateEnter(StateEnum state) = 0;
  virtual void HandleUserStateExit(StateEnum state) = 0;

  void EnableLogging() { machine_.EnableLoggingPublic(); }

 private:
  typedef StateMachineBase::State BaseState;
  typedef StateMachineBase::Event BaseEvent;

  // Private contained subclass that forwards and adapts all virtual methods
  // into this class's equivalent virtual methods.
  class WrappedMachine : public StateMachineBase {
   public:
    WrappedMachine(StateMachine<StateEnum, EventEnum>* wrapper,
                   const std::string& name)
        : StateMachineBase(name), wrapper_(wrapper) {}

    optional<State> GetUserParentState(State state) const override {
      optional<StateEnum> result =
          wrapper_->GetUserParentState(static_cast<StateEnum>(state));
      return (result ? static_cast<State>(*result) : optional<State>());
    }

    optional<State> GetUserInitialSubstate(State state) const override {
      optional<StateEnum> result =
          wrapper_->GetUserInitialSubstate(static_cast<StateEnum>(state));
      return (result ? static_cast<State>(*result) : optional<State>());
    }

    State GetUserInitialState() const override {
      return static_cast<State>(wrapper_->GetUserInitialState());
    }

    const char* GetUserStateString(State state) const override {
      return wrapper_->GetUserStateString(static_cast<StateEnum>(state));
    }

    const char* GetUserEventString(Event event) const override {
      return wrapper_->GetUserEventString(static_cast<EventEnum>(event));
    }

    Result HandleUserStateEvent(State state,
                                Event event,
                                void* data) override {
      typename StateMachine<StateEnum, EventEnum>::Result result =
          wrapper_->HandleUserStateEvent(static_cast<StateEnum>(state),
                                         static_cast<EventEnum>(event), data);
      if (result.is_transition) {
        return Result(static_cast<State>(*result.target), result.is_external);
      }

      return result.is_handled ? kHandled : kNotHandled;
    }

    void HandleUserStateEnter(State state) override {
      wrapper_->HandleUserStateEnter(static_cast<StateEnum>(state));
    }

    void HandleUserStateExit(State state) override {
      wrapper_->HandleUserStateExit(static_cast<StateEnum>(state));
    }

    // A public exposure of EnableLogging so the wrapper can access it. Since
    // this class is private to the wrapper, it is the only one who can see it.
    void EnableLoggingPublic() { EnableLogging(); }

   private:
    StateMachine<StateEnum, EventEnum>* wrapper_;
  };

  WrappedMachine machine_;
};

}  // namespace starboard

#endif  // STARBOARD_COMMON_STATE_MACHINE_H_
