// 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 "view_manager/public/cpp/view.h"

#include <set>
#include <string>

#include "mojo/public/cpp/application/service_provider_impl.h"
#include "view_manager/public/cpp/lib/view_manager_client_impl.h"
#include "view_manager/public/cpp/lib/view_private.h"
#include "view_manager/public/cpp/view_observer.h"
#include "view_manager/public/cpp/view_tracker.h"

namespace mojo {

namespace {

void NotifyViewTreeChangeAtReceiver(
    View* receiver,
    const ViewObserver::TreeChangeParams& params,
    bool change_applied) {
  ViewObserver::TreeChangeParams local_params = params;
  local_params.receiver = receiver;
  if (change_applied) {
    FOR_EACH_OBSERVER(ViewObserver,
                      *ViewPrivate(receiver).observers(),
                      OnTreeChanged(local_params));
  } else {
    FOR_EACH_OBSERVER(ViewObserver,
                      *ViewPrivate(receiver).observers(),
                      OnTreeChanging(local_params));
  }
}

void NotifyViewTreeChangeUp(
    View* start_at,
    const ViewObserver::TreeChangeParams& params,
    bool change_applied) {
  for (View* current = start_at; current; current = current->parent())
    NotifyViewTreeChangeAtReceiver(current, params, change_applied);
}

void NotifyViewTreeChangeDown(
    View* start_at,
    const ViewObserver::TreeChangeParams& params,
    bool change_applied) {
  NotifyViewTreeChangeAtReceiver(start_at, params, change_applied);
  View::Children::const_iterator it = start_at->children().begin();
  for (; it != start_at->children().end(); ++it)
    NotifyViewTreeChangeDown(*it, params, change_applied);
}

void NotifyViewTreeChange(
    const ViewObserver::TreeChangeParams& params,
    bool change_applied) {
  NotifyViewTreeChangeDown(params.target, params, change_applied);
  if (params.old_parent)
    NotifyViewTreeChangeUp(params.old_parent, params, change_applied);
  if (params.new_parent)
    NotifyViewTreeChangeUp(params.new_parent, params, change_applied);
}

class ScopedTreeNotifier {
 public:
  ScopedTreeNotifier(View* target, View* old_parent, View* new_parent) {
    params_.target = target;
    params_.old_parent = old_parent;
    params_.new_parent = new_parent;
    NotifyViewTreeChange(params_, false);
  }
  ~ScopedTreeNotifier() {
    NotifyViewTreeChange(params_, true);
  }

 private:
  ViewObserver::TreeChangeParams params_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
};

void RemoveChildImpl(View* child, View::Children* children) {
  View::Children::iterator it =
      std::find(children->begin(), children->end(), child);
  if (it != children->end()) {
    children->erase(it);
    ViewPrivate(child).ClearParent();
  }
}

class ScopedOrderChangedNotifier {
 public:
  ScopedOrderChangedNotifier(View* view,
                             View* relative_view,
                             OrderDirection direction)
      : view_(view),
        relative_view_(relative_view),
        direction_(direction) {
    FOR_EACH_OBSERVER(ViewObserver,
                      *ViewPrivate(view_).observers(),
                      OnViewReordering(view_, relative_view_, direction_));
  }
  ~ScopedOrderChangedNotifier() {
    FOR_EACH_OBSERVER(ViewObserver,
                      *ViewPrivate(view_).observers(),
                      OnViewReordered(view_, relative_view_, direction_));
  }

 private:
  View* view_;
  View* relative_view_;
  OrderDirection direction_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier);
};

// Returns true if the order actually changed.
bool ReorderImpl(View::Children* children,
                 View* view,
                 View* relative,
                 OrderDirection direction) {
  DCHECK(relative);
  DCHECK_NE(view, relative);
  DCHECK_EQ(view->parent(), relative->parent());

  const size_t child_i =
      std::find(children->begin(), children->end(), view) - children->begin();
  const size_t target_i =
      std::find(children->begin(), children->end(), relative) -
      children->begin();
  if ((direction == ORDER_DIRECTION_ABOVE && child_i == target_i + 1) ||
      (direction == ORDER_DIRECTION_BELOW && child_i + 1 == target_i)) {
    return false;
  }

  ScopedOrderChangedNotifier notifier(view, relative, direction);

  const size_t dest_i = direction == ORDER_DIRECTION_ABOVE
                            ? (child_i < target_i ? target_i : target_i + 1)
                            : (child_i < target_i ? target_i - 1 : target_i);
  children->erase(children->begin() + child_i);
  children->insert(children->begin() + dest_i, view);

  return true;
}

class ScopedSetBoundsNotifier {
 public:
  ScopedSetBoundsNotifier(View* view,
                          const Rect& old_bounds,
                          const Rect& new_bounds)
      : view_(view),
        old_bounds_(old_bounds),
        new_bounds_(new_bounds) {
    FOR_EACH_OBSERVER(ViewObserver,
                      *ViewPrivate(view_).observers(),
                      OnViewBoundsChanging(view_, old_bounds_, new_bounds_));
  }
  ~ScopedSetBoundsNotifier() {
    FOR_EACH_OBSERVER(ViewObserver,
                      *ViewPrivate(view_).observers(),
                      OnViewBoundsChanged(view_, old_bounds_, new_bounds_));
  }

 private:
  View* view_;
  const Rect old_bounds_;
  const Rect new_bounds_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier);
};

// Some operations are only permitted in the connection that created the view.
bool OwnsView(ViewManager* manager, View* view) {
  return !manager ||
      static_cast<ViewManagerClientImpl*>(manager)->OwnsView(view->id());
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// View, public:

void View::Destroy() {
  if (!OwnsView(manager_, this))
    return;

  if (manager_)
    static_cast<ViewManagerClientImpl*>(manager_)->DestroyView(id_);
  while (!children_.empty()) {
    View* child = children_.front();
    if (!OwnsView(manager_, child)) {
      ViewPrivate(child).ClearParent();
      children_.erase(children_.begin());
    } else {
      child->Destroy();
      DCHECK(std::find(children_.begin(), children_.end(), child) ==
             children_.end());
    }
  }
  LocalDestroy();
}

void View::SetBounds(const Rect& bounds) {
  if (!OwnsView(manager_, this))
    return;

  if (bounds_.Equals(bounds))
    return;

  if (manager_)
    static_cast<ViewManagerClientImpl*>(manager_)->SetBounds(id_, bounds);
  LocalSetBounds(bounds_, bounds);
}

void View::SetVisible(bool value) {
  if (visible_ == value)
    return;

  if (manager_)
    static_cast<ViewManagerClientImpl*>(manager_)->SetVisible(id_, value);
  LocalSetVisible(value);
}

void View::SetSharedProperty(const std::string& name,
                             const std::vector<uint8_t>* value) {
  std::vector<uint8_t> old_value;
  std::vector<uint8_t>* old_value_ptr = nullptr;
  auto it = properties_.find(name);
  if (it != properties_.end()) {
    old_value = it->second;
    old_value_ptr = &old_value;

    if (value && old_value == *value)
      return;
  } else if (!value) {
    // This property isn't set in |properties_| and |value| is NULL, so there's
    // no change.
    return;
  }

  if (value) {
    properties_[name] = *value;
  } else if (it != properties_.end()) {
    properties_.erase(it);
  }

  // TODO: add test coverage of this (450303).
  if (manager_) {
    Array<uint8_t> transport_value;
    if (value) {
      transport_value.resize(value->size());
      if (value->size())
        memcpy(&transport_value.front(), &(value->front()), value->size());
    }
    static_cast<ViewManagerClientImpl*>(manager_)->SetProperty(
        id_, name, transport_value.Pass());
  }

  FOR_EACH_OBSERVER(
      ViewObserver, observers_,
      OnViewSharedPropertyChanged(this, name, old_value_ptr, value));
}

bool View::IsDrawn() const {
  if (!visible_)
    return false;
  return parent_ ? parent_->IsDrawn() : drawn_;
}

void View::AddObserver(ViewObserver* observer) {
  observers_.AddObserver(observer);
}

void View::RemoveObserver(ViewObserver* observer) {
  observers_.RemoveObserver(observer);
}

const View* View::GetRoot() const {
  const View* root = this;
  for (const View* parent = this; parent; parent = parent->parent())
    root = parent;
  return root;
}

void View::AddChild(View* child) {
  // TODO(beng): not necessarily valid to all connections, but possibly to the
  //             embeddee in an embedder-embeddee relationship.
  if (manager_)
    CHECK_EQ(child->view_manager(), manager_);
  LocalAddChild(child);
  if (manager_)
    static_cast<ViewManagerClientImpl*>(manager_)->AddChild(child->id(), id_);
}

void View::RemoveChild(View* child) {
  // TODO(beng): not necessarily valid to all connections, but possibly to the
  //             embeddee in an embedder-embeddee relationship.
  if (manager_)
    CHECK_EQ(child->view_manager(), manager_);
  LocalRemoveChild(child);
  if (manager_) {
    static_cast<ViewManagerClientImpl*>(manager_)->RemoveChild(child->id(),
                                                               id_);
  }
}

void View::MoveToFront() {
  if (!parent_ || parent_->children_.back() == this)
    return;
  Reorder(parent_->children_.back(), ORDER_DIRECTION_ABOVE);
}

void View::MoveToBack() {
  if (!parent_ || parent_->children_.front() == this)
    return;
  Reorder(parent_->children_.front(), ORDER_DIRECTION_BELOW);
}

void View::Reorder(View* relative, OrderDirection direction) {
  if (!LocalReorder(relative, direction))
    return;
  if (manager_) {
    static_cast<ViewManagerClientImpl*>(manager_)->Reorder(id_,
                                                            relative->id(),
                                                            direction);
  }
}

bool View::Contains(View* child) const {
  if (!child)
    return false;
  if (child == this)
    return true;
  if (manager_)
    CHECK_EQ(child->view_manager(), manager_);
  for (View* p = child->parent(); p; p = p->parent()) {
    if (p == this)
      return true;
  }
  return false;
}

View* View::GetChildById(Id id) {
  if (id == id_)
    return this;
  // TODO(beng): this could be improved depending on how we decide to own views.
  Children::const_iterator it = children_.begin();
  for (; it != children_.end(); ++it) {
    View* view = (*it)->GetChildById(id);
    if (view)
      return view;
  }
  return NULL;
}

void View::SetSurfaceId(SurfaceIdPtr id) {
  if (manager_) {
    static_cast<ViewManagerClientImpl*>(manager_)->SetSurfaceId(id_, id.Pass());
  }
}

void View::SetFocus() {
  if (manager_)
    static_cast<ViewManagerClientImpl*>(manager_)->SetFocus(id_);
}

void View::Embed(const String& url) {
  static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_);
}

void View::Embed(const String& url,
                 InterfaceRequest<ServiceProvider> services,
                 ServiceProviderPtr exposed_services) {
  static_cast<ViewManagerClientImpl*>(manager_)
      ->Embed(url, id_, services.Pass(), exposed_services.Pass());
}

void View::Embed(ViewManagerClientPtr client) {
  static_cast<ViewManagerClientImpl*>(manager_)->Embed(id_, client.Pass());
}

////////////////////////////////////////////////////////////////////////////////
// View, protected:

namespace {

ViewportMetricsPtr CreateEmptyViewportMetrics() {
  ViewportMetricsPtr metrics = ViewportMetrics::New();
  metrics->size = Size::New();
  // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it
  // once that's fixed.
  return metrics.Pass();
}

}  // namespace

View::View()
    : manager_(NULL),
      id_(static_cast<Id>(-1)),
      parent_(NULL),
      viewport_metrics_(CreateEmptyViewportMetrics()),
      visible_(true),
      drawn_(false) {
}

View::~View() {
  FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroying(this));
  if (parent_)
    parent_->LocalRemoveChild(this);

  // We may still have children. This can happen if the embedder destroys the
  // root while we're still alive.
  while (!children_.empty()) {
    View* child = children_.front();
    LocalRemoveChild(child);
    DCHECK(children_.empty() || children_.front() != child);
  }

  // TODO(beng): It'd be better to do this via a destruction observer in the
  //             ViewManagerClientImpl.
  if (manager_)
    static_cast<ViewManagerClientImpl*>(manager_)->RemoveView(id_);

  // Clear properties.
  for (auto& pair : prop_map_) {
    if (pair.second.deallocator)
      (*pair.second.deallocator)(pair.second.value);
  }
  prop_map_.clear();

  FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroyed(this));
}

////////////////////////////////////////////////////////////////////////////////
// View, private:

View::View(ViewManager* manager, Id id)
    : manager_(manager),
      id_(id),
      parent_(nullptr),
      viewport_metrics_(CreateEmptyViewportMetrics()),
      visible_(false),
      drawn_(false) {
}

int64 View::SetLocalPropertyInternal(const void* key,
                                     const char* name,
                                     PropertyDeallocator deallocator,
                                     int64 value,
                                     int64 default_value) {
  int64 old = GetLocalPropertyInternal(key, default_value);
  if (value == default_value) {
    prop_map_.erase(key);
  } else {
    Value prop_value;
    prop_value.name = name;
    prop_value.value = value;
    prop_value.deallocator = deallocator;
    prop_map_[key] = prop_value;
  }
  FOR_EACH_OBSERVER(ViewObserver, observers_,
                    OnViewLocalPropertyChanged(this, key, old));
  return old;
}

int64 View::GetLocalPropertyInternal(const void* key,
                                     int64 default_value) const {
  std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
  if (iter == prop_map_.end())
    return default_value;
  return iter->second.value;
}

void View::LocalDestroy() {
  delete this;
}

void View::LocalAddChild(View* child) {
  ScopedTreeNotifier notifier(child, child->parent(), this);
  if (child->parent())
    RemoveChildImpl(child, &child->parent_->children_);
  children_.push_back(child);
  child->parent_ = this;
}

void View::LocalRemoveChild(View* child) {
  DCHECK_EQ(this, child->parent());
  ScopedTreeNotifier notifier(child, this, NULL);
  RemoveChildImpl(child, &children_);
}

bool View::LocalReorder(View* relative, OrderDirection direction) {
  return ReorderImpl(&parent_->children_, this, relative, direction);
}

void View::LocalSetBounds(const Rect& old_bounds,
                          const Rect& new_bounds) {
  DCHECK(old_bounds.x == bounds_.x);
  DCHECK(old_bounds.y == bounds_.y);
  DCHECK(old_bounds.width == bounds_.width);
  DCHECK(old_bounds.height == bounds_.height);
  ScopedSetBoundsNotifier notifier(this, old_bounds, new_bounds);
  bounds_ = new_bounds;
}

void View::LocalSetViewportMetrics(const ViewportMetrics& old_metrics,
                                   const ViewportMetrics& new_metrics) {
  // TODO(eseidel): We could check old_metrics against viewport_metrics_.
  viewport_metrics_ = new_metrics.Clone();
  FOR_EACH_OBSERVER(
      ViewObserver, observers_,
      OnViewViewportMetricsChanged(this, old_metrics, new_metrics));
}

void View::LocalSetDrawn(bool value) {
  if (drawn_ == value)
    return;

  // As IsDrawn() is derived from |visible_| and |drawn_|, only send drawn
  // notification is the value of IsDrawn() is really changing.
  if (IsDrawn() == value) {
    drawn_ = value;
    return;
  }
  FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanging(this));
  drawn_ = value;
  FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanged(this));
}

void View::LocalSetVisible(bool visible) {
  if (visible_ == visible)
    return;

  FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanging(this));
  visible_ = visible;
  NotifyViewVisibilityChanged(this);
}

void View::NotifyViewVisibilityChanged(View* target) {
  if (!NotifyViewVisibilityChangedDown(target)) {
    return; // |this| has been deleted.
  }
  NotifyViewVisibilityChangedUp(target);
}

bool View::NotifyViewVisibilityChangedAtReceiver(View* target) {
  // |this| may be deleted during a call to OnViewVisibilityChanged() on one
  // of the observers. We create an local observer for that. In that case we
  // exit without further access to any members.
  ViewTracker tracker;
  tracker.Add(this);
  FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanged(target));
  return tracker.Contains(this);
}

bool View::NotifyViewVisibilityChangedDown(View* target) {
  if (!NotifyViewVisibilityChangedAtReceiver(target))
    return false; // |this| was deleted.
  std::set<const View*> child_already_processed;
  bool child_destroyed = false;
  do {
    child_destroyed = false;
    for (View::Children::const_iterator it = children_.begin();
         it != children_.end(); ++it) {
      if (!child_already_processed.insert(*it).second)
        continue;
      if (!(*it)->NotifyViewVisibilityChangedDown(target)) {
        // |*it| was deleted, |it| is invalid and |children_| has changed.  We
        // exit the current for-loop and enter a new one.
        child_destroyed = true;
        break;
      }
    }
  } while (child_destroyed);
  return true;
}

void View::NotifyViewVisibilityChangedUp(View* target) {
  // Start with the parent as we already notified |this|
  // in NotifyViewVisibilityChangedDown.
  for (View* view = parent(); view; view = view->parent()) {
    bool ret = view->NotifyViewVisibilityChangedAtReceiver(target);
    DCHECK(ret);
  }
}

}  // namespace mojo
