// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/window.h"

#include <algorithm>

#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/base/tokens.h"
#include "cobalt/cssom/css_computed_style_declaration.h"
#include "cobalt/cssom/user_agent_style_sheet.h"
#include "cobalt/dom/camera_3d.h"
#include "cobalt/dom/console.h"
#include "cobalt/dom/device_orientation_event.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/error_event.h"
#include "cobalt/dom/error_event_init.h"
#include "cobalt/dom/event.h"
#include "cobalt/dom/history.h"
#include "cobalt/dom/html_element.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/keyboard_event.h"
#include "cobalt/dom/location.h"
#include "cobalt/dom/media_source.h"
#include "cobalt/dom/mouse_event.h"
#include "cobalt/dom/mutation_observer_task_manager.h"
#include "cobalt/dom/navigator.h"
#include "cobalt/dom/performance.h"
#include "cobalt/dom/pointer_event.h"
#include "cobalt/dom/screen.h"
#include "cobalt/dom/storage.h"
#include "cobalt/dom/wheel_event.h"
#include "cobalt/dom/window_timers.h"
#include "cobalt/media_session/media_session_client.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/speech/speech_synthesis.h"

using cobalt::media_session::MediaSession;

namespace cobalt {
namespace dom {

// This class fires the window's load event when the document is loaded.
class Window::RelayLoadEvent : public DocumentObserver {
 public:
  explicit RelayLoadEvent(Window* window) : window_(window) {}

  // From DocumentObserver.
  void OnLoad() OVERRIDE {
    window_->PostToDispatchEvent(FROM_HERE, base::Tokens::load());
  }
  void OnMutation() OVERRIDE {}
  void OnFocusChanged() OVERRIDE {}

 private:
  Window* window_;

  DISALLOW_COPY_AND_ASSIGN(RelayLoadEvent);
};

Window::Window(int width, int height, float device_pixel_ratio,
               base::ApplicationState initial_application_state,
               cssom::CSSParser* css_parser, Parser* dom_parser,
               loader::FetcherFactory* fetcher_factory,
               render_tree::ResourceProvider** resource_provider,
               loader::image::AnimatedImageTracker* animated_image_tracker,
               loader::image::ImageCache* image_cache,
               loader::image::ReducedCacheCapacityManager*
                   reduced_image_cache_capacity_manager,
               loader::font::RemoteTypefaceCache* remote_typeface_cache,
               loader::mesh::MeshCache* mesh_cache,
               LocalStorageDatabase* local_storage_database,
               media::CanPlayTypeHandler* can_play_type_handler,
               media::WebMediaPlayerFactory* web_media_player_factory,
               script::ExecutionState* execution_state,
               script::ScriptRunner* script_runner,
               script::ScriptValueFactory* script_value_factory,
               MediaSource::Registry* media_source_registry,
               DomStatTracker* dom_stat_tracker, const GURL& url,
               const std::string& user_agent, const std::string& language,
               const base::Callback<void(const GURL&)> navigation_callback,
               const base::Callback<void(const std::string&)>& error_callback,
               network_bridge::CookieJar* cookie_jar,
               const network_bridge::PostSender& post_sender,
               const std::string& default_security_policy,
               CspEnforcementType csp_enforcement_mode,
               const base::Closure& csp_policy_changed_callback,
               const base::Closure& ran_animation_frame_callbacks_callback,
               const base::Closure& window_close_callback,
               const base::Closure& window_minimize_callback,
               const scoped_refptr<input::Camera3D>& camera_3d,
               const scoped_refptr<MediaSession>& media_session,
               int csp_insecure_allowed_token, int dom_max_element_depth,
               float video_playback_rate_multiplier, ClockType clock_type,
               const base::Callback<bool(const std::string&)>&
                   splash_screen_cache_callback)
    : width_(width),
      height_(height),
      device_pixel_ratio_(device_pixel_ratio),
      is_resize_event_pending_(false),
      is_reporting_script_error_(false),
#if defined(ENABLE_TEST_RUNNER)
      test_runner_(new TestRunner()),
#endif  // ENABLE_TEST_RUNNER
      html_element_context_(new HTMLElementContext(
          fetcher_factory, css_parser, dom_parser, can_play_type_handler,
          web_media_player_factory, script_runner, script_value_factory,
          media_source_registry, resource_provider, animated_image_tracker,
          image_cache, reduced_image_cache_capacity_manager,
          remote_typeface_cache, mesh_cache, dom_stat_tracker, language,
          initial_application_state, video_playback_rate_multiplier)),
      performance_(new Performance(
#if defined(ENABLE_TEST_RUNNER)
          clock_type == kClockTypeTestRunner ? test_runner_->GetClock() :
#endif
                                             new base::SystemMonotonicClock())),
      ALLOW_THIS_IN_INITIALIZER_LIST(document_(new Document(
          html_element_context_.get(),
          Document::Options(
              url, this,
              base::Bind(&Window::FireHashChangeEvent, base::Unretained(this)),
              performance_->timing()->GetNavigationStartClock(),
              navigation_callback, ParseUserAgentStyleSheet(css_parser),
              math::Size(width_, height_), cookie_jar, post_sender,
              default_security_policy, csp_enforcement_mode,
              csp_policy_changed_callback, csp_insecure_allowed_token,
              dom_max_element_depth)))),
      document_loader_(NULL),
      history_(new History()),
      navigator_(new Navigator(user_agent, language, media_session,
                               script_value_factory)),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          relay_on_load_event_(new RelayLoadEvent(this))),
      console_(new Console(execution_state)),
      ALLOW_THIS_IN_INITIALIZER_LIST(window_timers_(new WindowTimers(this))),
      ALLOW_THIS_IN_INITIALIZER_LIST(animation_frame_request_callback_list_(
          new AnimationFrameRequestCallbackList(this))),
      crypto_(new Crypto()),
      speech_synthesis_(new speech::SpeechSynthesis(navigator_)),
      ALLOW_THIS_IN_INITIALIZER_LIST(local_storage_(
          new Storage(this, Storage::kLocalStorage, local_storage_database))),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          session_storage_(new Storage(this, Storage::kSessionStorage, NULL))),
      screen_(new Screen(width, height)),
      ran_animation_frame_callbacks_callback_(
          ran_animation_frame_callbacks_callback),
      window_close_callback_(window_close_callback),
      window_minimize_callback_(window_minimize_callback),
      splash_screen_cache_callback_(splash_screen_cache_callback) {
#if !defined(ENABLE_TEST_RUNNER)
  UNREFERENCED_PARAMETER(clock_type);
#endif
  document_->AddObserver(relay_on_load_event_.get());
  html_element_context_->page_visibility_state()->AddObserver(this);
  SetCamera3D(camera_3d);

  // Document load start is deferred from this constructor so that we can be
  // guaranteed that this Window object is fully constructed before document
  // loading begins.
  MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(&Window::StartDocumentLoad, this, fetcher_factory,
                            url, dom_parser, error_callback));
}

void Window::StartDocumentLoad(
    loader::FetcherFactory* fetcher_factory, const GURL& url,
    Parser* dom_parser,
    const base::Callback<void(const std::string&)>& error_callback) {
  document_loader_.reset(
      new loader::Loader(base::Bind(&loader::FetcherFactory::CreateFetcher,
                                    base::Unretained(fetcher_factory), url),
                         dom_parser->ParseDocumentAsync(
                             document_, base::SourceLocation(url.spec(), 1, 1)),
                         error_callback));
}

const scoped_refptr<Document>& Window::document() const { return document_; }

const scoped_refptr<Location>& Window::location() const {
  return document_->location();
}

const scoped_refptr<History>& Window::history() const { return history_; }

// https://www.w3.org/TR/html5/browsers.html#dom-window-close
void Window::Close() {
  LOG(INFO) << __func__;
  if (!window_close_callback_.is_null()) {
    window_close_callback_.Run();
  }
}

void Window::Minimize() {
  if (!window_minimize_callback_.is_null()) {
    window_minimize_callback_.Run();
  }
}

const scoped_refptr<Navigator>& Window::navigator() const { return navigator_; }

scoped_refptr<cssom::CSSStyleDeclaration> Window::GetComputedStyle(
    const scoped_refptr<Element>& elt) {
  scoped_refptr<HTMLElement> html_element = elt->AsHTMLElement();
  if (html_element) {
    document_->UpdateComputedStyleOnElementAndAncestor(html_element);
    return html_element->css_computed_style_declaration();
  }
  return NULL;
}

scoped_refptr<cssom::CSSStyleDeclaration> Window::GetComputedStyle(
    const scoped_refptr<Element>& elt, const std::string& pseudoElt) {
  // The getComputedStyle(elt, pseudoElt) method must run these steps:
  // https://www.w3.org/TR/2013/WD-cssom-20131205/#dom-window-getcomputedstyle

  // 1. Let doc be the Document associated with the Window object on which the
  // method was invoked.
  DCHECK_EQ(document_, elt->node_document())
      << "getComputedStyle not supported for elements outside of the document";

  scoped_refptr<HTMLElement> html_element = elt->AsHTMLElement();
  scoped_refptr<cssom::CSSComputedStyleDeclaration> obj;
  if (html_element) {
    document_->UpdateComputedStyleOnElementAndAncestor(html_element);

    // 2. Let obj be elt.
    obj = html_element->css_computed_style_declaration();

    // 3. If pseudoElt is as an ASCII case-insensitive match for either
    // ':before' or '::before' let obj be the ::before pseudo-element of elt.
    if (LowerCaseEqualsASCII(pseudoElt, ":before") ||
        LowerCaseEqualsASCII(pseudoElt, "::before")) {
      PseudoElement* pseudo_element =
          html_element->pseudo_element(kBeforePseudoElementType);
      obj = pseudo_element ? pseudo_element->css_computed_style_declaration()
                           : NULL;
    }

    // 4. If pseudoElt is as an ASCII case-insensitive match for either ':after'
    // or '::after' let obj be the ::after pseudo-element of elt.
    if (LowerCaseEqualsASCII(pseudoElt, ":after") ||
        LowerCaseEqualsASCII(pseudoElt, "::after")) {
      PseudoElement* pseudo_element =
          html_element->pseudo_element(kAfterPseudoElementType);
      obj = pseudo_element ? pseudo_element->css_computed_style_declaration()
                           : NULL;
    }
  }
  // 5. Return a live CSS declaration block.
  return obj;
}

int32 Window::RequestAnimationFrame(
    const AnimationFrameRequestCallbackList::FrameRequestCallbackArg&
        callback) {
  return animation_frame_request_callback_list_->RequestAnimationFrame(
      callback);
}

void Window::CancelAnimationFrame(int32 handle) {
  animation_frame_request_callback_list_->CancelAnimationFrame(handle);
}

scoped_refptr<MediaQueryList> Window::MatchMedia(const std::string& query) {
  DCHECK(html_element_context_->css_parser());
  scoped_refptr<cssom::MediaList> media_list =
      html_element_context_->css_parser()->ParseMediaList(
          query, GetInlineSourceLocation());
  return make_scoped_refptr(new MediaQueryList(media_list, screen_));
}

const scoped_refptr<Screen>& Window::screen() { return screen_; }

scoped_refptr<Crypto> Window::crypto() const { return crypto_; }

std::string Window::Btoa(const std::string& string_to_encode) {
  std::string output;
  base::Base64Encode(string_to_encode, &output);
  return output;
}

std::string Window::Atob(const std::string& encoded_string) {
  std::string output;
  base::Base64Decode(encoded_string, &output);
  return output;
}

int Window::SetTimeout(const WindowTimers::TimerCallbackArg& handler,
                       int timeout) {
  DLOG_IF(WARNING, timeout < 0)
      << "Window::SetTimeout received negative timeout: " << timeout;
  timeout = std::max(timeout, 0);

  int return_value = 0;
  if (window_timers_) {
    return_value = window_timers_->SetTimeout(handler, timeout);
  } else {
    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
  }

  return return_value;
}

void Window::ClearTimeout(int handle) {
  if (window_timers_) {
    window_timers_->ClearTimeout(handle);
  } else {
    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
  }
}

int Window::SetInterval(const WindowTimers::TimerCallbackArg& handler,
                        int timeout) {
  DLOG_IF(WARNING, timeout < 0)
      << "Window::SetInterval received negative timeout: " << timeout;
  timeout = std::max(timeout, 0);

  int return_value = 0;
  if (window_timers_) {
    return_value = window_timers_->SetInterval(handler, timeout);
  } else {
    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
  }

  return return_value;
}

void Window::ClearInterval(int handle) {
  if (window_timers_) {
    window_timers_->ClearInterval(handle);
  } else {
    DLOG(WARNING) << "window_timers_ does not exist.  Already destroyed?";
  }
}

void Window::DestroyTimers() { window_timers_.reset(); }

scoped_refptr<Storage> Window::local_storage() const { return local_storage_; }

scoped_refptr<Storage> Window::session_storage() const {
  return session_storage_;
}

const scoped_refptr<Performance>& Window::performance() const {
  return performance_;
}

scoped_refptr<speech::SpeechSynthesis> Window::speech_synthesis() const {
  return speech_synthesis_;
}

const scoped_refptr<Console>& Window::console() const { return console_; }

const scoped_refptr<Camera3D>& Window::camera_3d() const { return camera_3d_; }

#if defined(ENABLE_TEST_RUNNER)
const scoped_refptr<TestRunner>& Window::test_runner() const {
  return test_runner_;
}
#endif  // ENABLE_TEST_RUNNER

void Window::Gc(script::EnvironmentSettings* settings) {
  if (settings) {
    DOMSettings* dom_settings =
        base::polymorphic_downcast<dom::DOMSettings*>(settings);
    dom_settings->javascript_engine()->CollectGarbage();
  }
}

HTMLElementContext* Window::html_element_context() const {
  return html_element_context_.get();
}

void Window::RunAnimationFrameCallbacks() {
  // Scope the StopWatch. It should not include any processing from
  // |ran_animation_frame_callbacks_callback_|.
  {
    base::StopWatch stop_watch_run_animation_frame_callbacks(
        DomStatTracker::kStopWatchTypeRunAnimationFrameCallbacks,
        base::StopWatch::kAutoStartOn,
        html_element_context()->dom_stat_tracker());

    // First grab the current list of frame request callbacks and hold on to it
    // here locally.
    scoped_ptr<AnimationFrameRequestCallbackList> frame_request_list =
        animation_frame_request_callback_list_.Pass();

    // Then setup the Window's frame request callback list with a freshly
    // created and empty one.
    animation_frame_request_callback_list_.reset(
        new AnimationFrameRequestCallbackList(this));

    // Now, iterate through each of the callbacks and call them.
    frame_request_list->RunCallbacks(*document_->timeline()->current_time());
  }

  // Run the callback if one exists.
  if (!ran_animation_frame_callbacks_callback_.is_null()) {
    ran_animation_frame_callbacks_callback_.Run();
  }
}

bool Window::HasPendingAnimationFrameCallbacks() const {
  return animation_frame_request_callback_list_->HasPendingCallbacks();
}

void Window::InjectEvent(const scoped_refptr<Event>& event) {
  // Forward the event on to the correct object in DOM.
  if (event->GetWrappableType() == base::GetTypeId<KeyboardEvent>()) {
    // Event.target:focused element processing the key event or if no element
    // focused, then the body element if available, otherwise the root element.
    //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-keydown
    //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-keypress
    //   https://www.w3.org/TR/2016/WD-uievents-20160804/#event-type-keyup
    if (document_->active_element()) {
      document_->active_element()->DispatchEvent(event);
    } else {
      document_->DispatchEvent(event);
    }
  } else if (event->GetWrappableType() == base::GetTypeId<PointerEvent>() ||
             event->GetWrappableType() == base::GetTypeId<MouseEvent>() ||
             event->GetWrappableType() == base::GetTypeId<WheelEvent>()) {
    document_->pointer_state()->QueuePointerEvent(event);
  } else {
    SB_NOTREACHED();
  }
}

void Window::SetApplicationState(base::ApplicationState state) {
  html_element_context_->page_visibility_state()->SetApplicationState(state);
}

bool Window::ReportScriptError(const script::ErrorReport& error_report) {
  // Runtime script errors: when the user agent is required to report an error
  // for a particular script, it must run these steps, after which the error is
  // either handled or not handled:
  //   https://www.w3.org/TR/html5/webappapis.html#runtime-script-errors

  // 1. If target is in error reporting mode, then abort these steps; the error
  //    is not handled.
  if (is_reporting_script_error_) {
    return false;
  }

  // 2. Let target be in error reporting mode.
  is_reporting_script_error_ = true;

  // 7. Let event be a new trusted ErrorEvent object that does not bubble but is
  //    cancelable, and which has the event name error.
  // NOTE: Cobalt does not currently support trusted events.
  ErrorEventInit error_event_init;
  error_event_init.set_bubbles(false);
  error_event_init.set_cancelable(true);

  if (error_report.is_muted) {
    // 6. If script has muted errors, then set message to "Script error.", set
    //    location to the empty string, set line and col to 0, and set error
    //    object to null.
    error_event_init.set_message("Script error.");
    error_event_init.set_filename("");
    error_event_init.set_lineno(0);
    error_event_init.set_colno(0);
    error_event_init.set_error(NULL);
  } else {
    // 8. Initialize event's message attribute to message.
    error_event_init.set_message(error_report.message);
    // 9. Initialize event's filename attribute to location.
    error_event_init.set_filename(error_report.filename);
    // 10. Initialize event's lineno attribute to line.
    error_event_init.set_lineno(error_report.line_number);
    // 11. Initialize event's colno attribute to col.
    error_event_init.set_colno(error_report.column_number);
    // 12. Initialize event's error attribute to error object.
    error_event_init.set_error(error_report.error ? error_report.error.get()
                                                  : NULL);
  }

  scoped_refptr<ErrorEvent> error_event(
      new ErrorEvent(base::Tokens::error(), error_event_init));

  // 13. Dispatch event at target.
  DispatchEvent(error_event);

  // 14. Let target no longer be in error reporting mode.
  is_reporting_script_error_ = false;

  // 15. If event was canceled, then the error is handled. Otherwise, the error
  //     is not handled.
  return error_event->default_prevented();
}

void Window::SetSynchronousLayoutCallback(
    const base::Closure& synchronous_layout_callback) {
  document_->set_synchronous_layout_callback(synchronous_layout_callback);
}

void Window::SetSize(int width, int height, float device_pixel_ratio) {
  if (width_ == width && height_ == height &&
      device_pixel_ratio_ == device_pixel_ratio) {
    return;
  }

  width_ = width;
  height_ = height;
  device_pixel_ratio_ = device_pixel_ratio;
  screen_->SetSize(width, height);

  // This will cause layout invalidation.
  document_->SetViewport(math::Size(width, height));

  if (html_element_context_->page_visibility_state()->GetVisibilityState() ==
      page_visibility::kVisibilityStateVisible) {
    DispatchEvent(new Event(base::Tokens::resize()));
  } else {
    is_resize_event_pending_ = true;
  }
}

void Window::SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d) {
  camera_3d_ = new Camera3D(camera_3d);
  camera_3d_->StartOrientationEvents(base::AsWeakPtr(this));
}

void Window::OnWindowFocusChanged(bool has_focus) {
  DispatchEvent(
      new Event(has_focus ? base::Tokens::focus() : base::Tokens::blur()));
}

void Window::OnVisibilityStateChanged(
    page_visibility::VisibilityState visibility_state) {
  if (is_resize_event_pending_ &&
      visibility_state == page_visibility::kVisibilityStateVisible) {
    is_resize_event_pending_ = false;
    DispatchEvent(new Event(base::Tokens::resize()));
  }
}

void Window::TraceMembers(script::Tracer* tracer) {
  tracer->Trace(performance_);
  tracer->Trace(document_);
  tracer->Trace(history_);
  tracer->Trace(navigator_);
  tracer->Trace(console_);
  tracer->Trace(camera_3d_);
  tracer->Trace(crypto_);
  tracer->Trace(speech_synthesis_);
  tracer->Trace(local_storage_);
  tracer->Trace(session_storage_);
  tracer->Trace(screen_);
}

Window::~Window() {
  html_element_context_->page_visibility_state()->RemoveObserver(this);
}

void Window::FireHashChangeEvent() {
  PostToDispatchEvent(FROM_HERE, base::Tokens::hashchange());
}

}  // namespace dom
}  // namespace cobalt
