// Copyright (c) 2013 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.
//
// DeclarativeRule<>, DeclarativeConditionSet<>, and DeclarativeActionSet<>
// templates usable with multiple different declarativeFoo systems.  These are
// templated on the Condition and Action types that define the behavior of a
// particular declarative event.

#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_DECLARATIVE_RULE_H__
#define EXTENSIONS_BROWSER_API_DECLARATIVE_DECLARATIVE_RULE_H__

#include <limits>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "components/url_matcher/url_matcher.h"
#include "extensions/common/api/events.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_id.h"

namespace base {
class Time;
class Value;
}

namespace content {
class BrowserContext;
}

namespace extensions {

// This class stores a set of conditions that may be part of a DeclarativeRule.
// If any condition is fulfilled, the Actions of the DeclarativeRule can be
// triggered.
//
// ConditionT should be immutable after creation.  It must define the following
// members:
//
//   // Arguments passed through from DeclarativeConditionSet::Create.
//   static std::unique_ptr<ConditionT> Create(
//       const Extension* extension,
//       URLMatcherConditionFactory* url_matcher_condition_factory,
//       // Except this argument gets elements of the Values array.
//       const base::Value& definition,
//       std::string* error);
//   // If the Condition needs to be filtered by some URLMatcherConditionSets,
//   // append them to |condition_sets|.
//   // DeclarativeConditionSet::GetURLMatcherConditionSets forwards here.
//   void GetURLMatcherConditionSets(
//       URLMatcherConditionSet::Vector* condition_sets);
//   // |match_data| passed through from DeclarativeConditionSet::IsFulfilled.
//   bool IsFulfilled(const ConditionT::MatchData& match_data);
template<typename ConditionT>
class DeclarativeConditionSet {
 public:
  typedef std::vector<std::unique_ptr<base::Value>> Values;
  typedef std::vector<linked_ptr<const ConditionT> > Conditions;
  typedef typename Conditions::const_iterator const_iterator;

  // Factory method that creates a DeclarativeConditionSet for |extension|
  // according to the JSON array |conditions| passed by the extension API. Sets
  // |error| and returns NULL in case of an error.
  static std::unique_ptr<DeclarativeConditionSet> Create(
      const Extension* extension,
      url_matcher::URLMatcherConditionFactory* url_matcher_condition_factory,
      const Values& condition_values,
      std::string* error);

  const Conditions& conditions() const {
    return conditions_;
  }

  const_iterator begin() const { return conditions_.begin(); }
  const_iterator end() const { return conditions_.end(); }

  // If |url_match_trigger| is not -1, this function looks for a condition
  // with this URLMatcherConditionSet, and forwards to that condition's
  // IsFulfilled(|match_data|). If there is no such condition, then false is
  // returned. If |url_match_trigger| is -1, this function returns whether any
  // of the conditions without URL attributes is satisfied.
  bool IsFulfilled(url_matcher::URLMatcherConditionSet::ID url_match_trigger,
                   const typename ConditionT::MatchData& match_data) const;

  // Appends the URLMatcherConditionSet from all conditions to |condition_sets|.
  void GetURLMatcherConditionSets(
      url_matcher::URLMatcherConditionSet::Vector* condition_sets) const;

  // Returns whether there are some conditions without UrlFilter attributes.
  bool HasConditionsWithoutUrls() const {
    return !conditions_without_urls_.empty();
  }

 private:
  typedef std::map<url_matcher::URLMatcherConditionSet::ID, const ConditionT*>
      URLMatcherIdToCondition;

  DeclarativeConditionSet(
      const Conditions& conditions,
      const URLMatcherIdToCondition& match_id_to_condition,
      const std::vector<const ConditionT*>& conditions_without_urls);

  const URLMatcherIdToCondition match_id_to_condition_;
  const Conditions conditions_;
  const std::vector<const ConditionT*> conditions_without_urls_;

  DISALLOW_COPY_AND_ASSIGN(DeclarativeConditionSet);
};

// Immutable container for multiple actions.
//
// ActionT should be immutable after creation.  It must define the following
// members:
//
//   // Arguments passed through from ActionSet::Create.
//   static std::unique_ptr<ActionT> Create(
//       const Extension* extension,
//       // Except this argument gets elements of the Values array.
//       const base::Value& definition,
//       std::string* error, bool* bad_message);
//   void Apply(const std::string& extension_id,
//              const base::Time& extension_install_time,
//              // Contains action-type-specific in/out parameters.
//              typename ActionT::ApplyInfo* apply_info) const;
//   // Only needed if the RulesRegistry calls DeclarativeActionSet::Revert().
//   void Revert(const std::string& extension_id,
//               const base::Time& extension_install_time,
//               // Contains action-type-specific in/out parameters.
//               typename ActionT::ApplyInfo* apply_info) const;
//   // Return the minimum priority of rules that can be evaluated after this
//   // action runs.  A suitable default value is MIN_INT.
//   int minimum_priority() const;
//
// TODO(battre): As DeclarativeActionSet can become the single owner of all
// actions, we can optimize here by making some of them singletons (e.g. Cancel
// actions).
template<typename ActionT>
class DeclarativeActionSet {
 public:
  typedef std::vector<std::unique_ptr<base::Value>> Values;
  typedef std::vector<scoped_refptr<const ActionT> > Actions;

  explicit DeclarativeActionSet(const Actions& actions);

  // Factory method that instantiates a DeclarativeActionSet for |extension|
  // according to |actions| which represents the array of actions received from
  // the extension API.
  static std::unique_ptr<DeclarativeActionSet> Create(
      content::BrowserContext* browser_context,
      const Extension* extension,
      const Values& action_values,
      std::string* error,
      bool* bad_message);

  // Rules call this method when their conditions are fulfilled.
  void Apply(const std::string& extension_id,
             const base::Time& extension_install_time,
             typename ActionT::ApplyInfo* apply_info) const;

  // Rules call this method when their conditions are fulfilled, but Apply has
  // already been called.
  void Reapply(const std::string& extension_id,
               const base::Time& extension_install_time,
               typename ActionT::ApplyInfo* apply_info) const;

  // Rules call this method when they have stateful conditions, and those
  // conditions stop being fulfilled.  Rules with event-based conditions (e.g. a
  // network request happened) will never Revert() an action.
  void Revert(const std::string& extension_id,
              const base::Time& extension_install_time,
              typename ActionT::ApplyInfo* apply_info) const;

  // Returns the minimum priority of rules that may be evaluated after
  // this rule. Defaults to MIN_INT.
  int GetMinimumPriority() const;

  const Actions& actions() const { return actions_; }

 private:
  const Actions actions_;

  DISALLOW_COPY_AND_ASSIGN(DeclarativeActionSet);
};

// Representation of a rule of a declarative API:
// https://developer.chrome.com/beta/extensions/events.html#declarative.
// Generally a RulesRegistry will hold a collection of Rules for a given
// declarative API and contain the logic for matching and applying them.
//
// See DeclarativeConditionSet and DeclarativeActionSet for the requirements on
// ConditionT and ActionT.
template<typename ConditionT, typename ActionT>
class DeclarativeRule {
 public:
  typedef std::string RuleId;
  typedef std::pair<ExtensionId, RuleId> GlobalRuleId;
  typedef int Priority;
  typedef DeclarativeConditionSet<ConditionT> ConditionSet;
  typedef DeclarativeActionSet<ActionT> ActionSet;
  typedef extensions::api::events::Rule JsonRule;
  typedef std::vector<std::string> Tags;

  // Checks whether the set of |conditions| and |actions| are consistent.
  // Returns true in case of consistency and MUST set |error| otherwise.
  typedef base::Callback<bool(const ConditionSet* conditions,
                              const ActionSet* actions,
                              std::string* error)> ConsistencyChecker;

  DeclarativeRule(const GlobalRuleId& id,
                  const Tags& tags,
                  base::Time extension_installation_time,
                  std::unique_ptr<ConditionSet> conditions,
                  std::unique_ptr<ActionSet> actions,
                  Priority priority);

  // Creates a DeclarativeRule for |extension| given a json definition.  The
  // format of each condition and action's json is up to the specific ConditionT
  // and ActionT.  |extension| may be NULL in tests.
  //
  // Before constructing the final rule, calls check_consistency(conditions,
  // actions, error) and returns NULL if it fails.  Pass NULL if no consistency
  // check is needed.  If |error| is empty, the translation was successful and
  // the returned rule is internally consistent.
  static std::unique_ptr<DeclarativeRule> Create(
      url_matcher::URLMatcherConditionFactory* url_matcher_condition_factory,
      content::BrowserContext* browser_context,
      const Extension* extension,
      base::Time extension_installation_time,
      linked_ptr<JsonRule> rule,
      ConsistencyChecker check_consistency,
      std::string* error);

  const GlobalRuleId& id() const { return id_; }
  const Tags& tags() const { return tags_; }
  const std::string& extension_id() const { return id_.first; }
  const ConditionSet& conditions() const { return *conditions_; }
  const ActionSet& actions() const { return *actions_; }
  Priority priority() const { return priority_; }

  // Calls actions().Apply(extension_id(), extension_installation_time_,
  // apply_info). This function should only be called when the conditions_ are
  // fulfilled (from a semantic point of view; no harm is done if this function
  // is called at other times for testing purposes).
  void Apply(typename ActionT::ApplyInfo* apply_info) const;

  // Returns the minimum priority of rules that may be evaluated after
  // this rule. Defaults to MIN_INT. Only valid if the conditions of this rule
  // are fulfilled.
  Priority GetMinimumPriority() const;

 private:
  GlobalRuleId id_;
  Tags tags_;
  base::Time extension_installation_time_;  // For precedences of rules.
  std::unique_ptr<ConditionSet> conditions_;
  std::unique_ptr<ActionSet> actions_;
  Priority priority_;

  DISALLOW_COPY_AND_ASSIGN(DeclarativeRule);
};

// Implementation details below here.

//
// DeclarativeConditionSet
//

template<typename ConditionT>
bool DeclarativeConditionSet<ConditionT>::IsFulfilled(
    url_matcher::URLMatcherConditionSet::ID url_match_trigger,
    const typename ConditionT::MatchData& match_data) const {
  if (url_match_trigger == -1) {
    // Invalid trigger -- indication that we should only check conditions
    // without URL attributes.
    for (const ConditionT* condition : conditions_without_urls_) {
      if (condition->IsFulfilled(match_data))
        return true;
    }
    return false;
  }

  typename URLMatcherIdToCondition::const_iterator triggered =
      match_id_to_condition_.find(url_match_trigger);
  return (triggered != match_id_to_condition_.end() &&
          triggered->second->IsFulfilled(match_data));
}

template<typename ConditionT>
void DeclarativeConditionSet<ConditionT>::GetURLMatcherConditionSets(
    url_matcher::URLMatcherConditionSet::Vector* condition_sets) const {
  for (const linked_ptr<const ConditionT>& condition : conditions_)
    condition->GetURLMatcherConditionSets(condition_sets);
}

// static
template <typename ConditionT>
std::unique_ptr<DeclarativeConditionSet<ConditionT>>
DeclarativeConditionSet<ConditionT>::Create(
    const Extension* extension,
    url_matcher::URLMatcherConditionFactory* url_matcher_condition_factory,
    const Values& condition_values,
    std::string* error) {
  Conditions result;

  for (const std::unique_ptr<base::Value>& value : condition_values) {
    CHECK(value.get());
    std::unique_ptr<ConditionT> condition = ConditionT::Create(
        extension, url_matcher_condition_factory, *value, error);
    if (!error->empty())
      return std::unique_ptr<DeclarativeConditionSet>();
    result.push_back(make_linked_ptr(condition.release()));
  }

  URLMatcherIdToCondition match_id_to_condition;
  std::vector<const ConditionT*> conditions_without_urls;
  url_matcher::URLMatcherConditionSet::Vector condition_sets;

  for (const linked_ptr<const ConditionT>& condition : result) {
    condition_sets.clear();
    condition->GetURLMatcherConditionSets(&condition_sets);
    if (condition_sets.empty()) {
      conditions_without_urls.push_back(condition.get());
    } else {
      for (const scoped_refptr<url_matcher::URLMatcherConditionSet>& match_set :
           condition_sets)
        match_id_to_condition[match_set->id()] = condition.get();
    }
  }

  return base::WrapUnique(new DeclarativeConditionSet(
      result, match_id_to_condition, conditions_without_urls));
}

template<typename ConditionT>
DeclarativeConditionSet<ConditionT>::DeclarativeConditionSet(
    const Conditions& conditions,
    const URLMatcherIdToCondition& match_id_to_condition,
    const std::vector<const ConditionT*>& conditions_without_urls)
    : match_id_to_condition_(match_id_to_condition),
      conditions_(conditions),
      conditions_without_urls_(conditions_without_urls) {}

//
// DeclarativeActionSet
//

template<typename ActionT>
DeclarativeActionSet<ActionT>::DeclarativeActionSet(const Actions& actions)
    : actions_(actions) {}

// static
template <typename ActionT>
std::unique_ptr<DeclarativeActionSet<ActionT>>
DeclarativeActionSet<ActionT>::Create(content::BrowserContext* browser_context,
                                      const Extension* extension,
                                      const Values& action_values,
                                      std::string* error,
                                      bool* bad_message) {
  *error = "";
  *bad_message = false;
  Actions result;

  for (const std::unique_ptr<base::Value>& value : action_values) {
    CHECK(value.get());
    scoped_refptr<const ActionT> action =
        ActionT::Create(browser_context, extension, *value, error, bad_message);
    if (!error->empty() || *bad_message)
      return std::unique_ptr<DeclarativeActionSet>();
    result.push_back(action);
  }

  return std::unique_ptr<DeclarativeActionSet>(
      new DeclarativeActionSet(result));
}

template<typename ActionT>
void DeclarativeActionSet<ActionT>::Apply(
    const std::string& extension_id,
    const base::Time& extension_install_time,
    typename ActionT::ApplyInfo* apply_info) const {
  for (const scoped_refptr<const ActionT>& action : actions_)
    action->Apply(extension_id, extension_install_time, apply_info);
}

template<typename ActionT>
void DeclarativeActionSet<ActionT>::Reapply(
    const std::string& extension_id,
    const base::Time& extension_install_time,
    typename ActionT::ApplyInfo* apply_info) const {
  for (const scoped_refptr<const ActionT>& action : actions_)
    action->Reapply(extension_id, extension_install_time, apply_info);
}

template<typename ActionT>
void DeclarativeActionSet<ActionT>::Revert(
    const std::string& extension_id,
    const base::Time& extension_install_time,
    typename ActionT::ApplyInfo* apply_info) const {
  for (const scoped_refptr<const ActionT>& action : actions_)
    action->Revert(extension_id, extension_install_time, apply_info);
}

template<typename ActionT>
int DeclarativeActionSet<ActionT>::GetMinimumPriority() const {
  int minimum_priority = std::numeric_limits<int>::min();
  for (typename Actions::const_iterator i = actions_.begin();
       i != actions_.end(); ++i) {
    minimum_priority = std::max(minimum_priority, (*i)->minimum_priority());
  }
  return minimum_priority;
}

//
// DeclarativeRule
//

template <typename ConditionT, typename ActionT>
DeclarativeRule<ConditionT, ActionT>::DeclarativeRule(
    const GlobalRuleId& id,
    const Tags& tags,
    base::Time extension_installation_time,
    std::unique_ptr<ConditionSet> conditions,
    std::unique_ptr<ActionSet> actions,
    Priority priority)
    : id_(id),
      tags_(tags),
      extension_installation_time_(extension_installation_time),
      conditions_(conditions.release()),
      actions_(actions.release()),
      priority_(priority) {
  CHECK(conditions_.get());
  CHECK(actions_.get());
}

// static
template <typename ConditionT, typename ActionT>
std::unique_ptr<DeclarativeRule<ConditionT, ActionT>>
DeclarativeRule<ConditionT, ActionT>::Create(
    url_matcher::URLMatcherConditionFactory* url_matcher_condition_factory,
    content::BrowserContext* browser_context,
    const Extension* extension,
    base::Time extension_installation_time,
    linked_ptr<JsonRule> rule,
    ConsistencyChecker check_consistency,
    std::string* error) {
  std::unique_ptr<DeclarativeRule> error_result;

  std::unique_ptr<ConditionSet> conditions = ConditionSet::Create(
      extension, url_matcher_condition_factory, rule->conditions, error);
  if (!error->empty())
    return std::move(error_result);
  CHECK(conditions.get());

  bool bad_message = false;
  std::unique_ptr<ActionSet> actions = ActionSet::Create(
      browser_context, extension, rule->actions, error, &bad_message);
  if (bad_message) {
    // TODO(battre) Export concept of bad_message to caller, the extension
    // should be killed in case it is true.
    *error = "An action of a rule set had an invalid "
        "structure that should have been caught by the JSON validator.";
    return std::move(error_result);
  }
  if (!error->empty() || bad_message)
    return std::move(error_result);
  CHECK(actions.get());

  if (!check_consistency.is_null() &&
      !check_consistency.Run(conditions.get(), actions.get(), error)) {
    DCHECK(!error->empty());
    return std::move(error_result);
  }

  CHECK(rule->priority.get());
  int priority = *(rule->priority);

  GlobalRuleId rule_id(extension->id(), *(rule->id));
  Tags tags = rule->tags ? *rule->tags : Tags();
  return std::unique_ptr<DeclarativeRule>(
      new DeclarativeRule(rule_id, tags, extension_installation_time,
                          std::move(conditions), std::move(actions), priority));
}

template<typename ConditionT, typename ActionT>
void DeclarativeRule<ConditionT, ActionT>::Apply(
    typename ActionT::ApplyInfo* apply_info) const {
  return actions_->Apply(extension_id(),
                         extension_installation_time_,
                         apply_info);
}

template<typename ConditionT, typename ActionT>
int DeclarativeRule<ConditionT, ActionT>::GetMinimumPriority() const {
  return actions_->GetMinimumPriority();
}

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_DECLARATIVE_RULE_H__
