// Aseprite
// Copyright (C) 2019-2024  Igara Studio S.A.
// Copyright (C) 2001-2018  David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.

#ifndef APP_UI_DOC_VIEW_H_INCLUDED
#define APP_UI_DOC_VIEW_H_INCLUDED
#pragma once

#include "app/doc_observer.h"
#include "app/ui/input_chain_element.h"
#include "app/ui/tabs.h"
#include "app/ui/workspace_view.h"
#include "ui/box.h"

namespace doc {
class Layer;
}

namespace ui {
class View;
}

namespace app {
class Doc;
class Editor;
class Site;

class DocViewPreviewDelegate {
public:
  virtual ~DocViewPreviewDelegate() {}
  virtual void onScrollOtherEditor(Editor* editor) = 0;
  virtual void onDisposeOtherEditor(Editor* editor) = 0;
  virtual void onPreviewOtherEditor(Editor* editor) = 0;
  virtual void onTagChangeEditor(Editor* editor, DocEvent& ev) = 0;
};

class DocView : public ui::Box,
                public TabView,
                public app::DocObserver,
                public WorkspaceView,
                public app::InputChainElement {
public:
  enum Type { Normal, Preview };

  DocView(Doc* document, Type type, DocViewPreviewDelegate* previewDelegate);
  ~DocView();

  Doc* document() const { return m_document; }
  Editor* editor() { return m_editor; }
  ui::View* viewWidget() const { return m_view; }
  void getSite(Site* site) const;

  bool isPreview() { return m_type == Preview; }

  // Preferred timeline scroll
  const gfx::Point& timelineScroll() { return m_timelineScroll; }
  void setTimelineScroll(const gfx::Point& pt) { m_timelineScroll = pt; }

  // TabView implementation
  std::string getTabText() override;
  TabIcon getTabIcon() override;
  gfx::Color getTabColor() override;

  // WorkspaceView implementation
  ui::Widget* getContentWidget() override { return this; }
  bool canCloneWorkspaceView() override { return true; }
  WorkspaceView* cloneWorkspaceView() override;
  void onWorkspaceViewSelected() override;
  void onClonedFrom(WorkspaceView* from) override;
  bool onCloseView(Workspace* workspace, bool quitting) override;
  void onTabPopup(Workspace* workspace) override;
  InputChainElement* onGetInputChainElement() override { return this; }

  // DocObserver implementation
  void onGeneralUpdate(DocEvent& ev) override;
  void onSpritePixelsModified(DocEvent& ev) override;
  void onLayerMergedDown(DocEvent& ev) override;
  void onAddLayer(DocEvent& ev) override;
  void onAddFrame(DocEvent& ev) override;
  void onRemoveFrame(DocEvent& ev) override;
  void onTagChange(DocEvent& ev) override;
  void onAddCel(DocEvent& ev) override;
  void onAfterRemoveCel(DocEvent& ev) override;
  void onTotalFramesChanged(DocEvent& ev) override;
  void onLayerRestacked(DocEvent& ev) override;
  void onAfterLayerVisibilityChange(DocEvent& ev) override;
  void onTilesetChanged(DocEvent& ev) override;

  // InputChainElement impl
  void onNewInputPriority(InputChainElement* element, const ui::Message* msg) override;
  bool onCanCut(Context* ctx) override;
  bool onCanCopy(Context* ctx) override;
  bool onCanPaste(Context* ctx) override;
  bool onCanClear(Context* ctx) override;
  bool onCut(Context* ctx) override;
  bool onCopy(Context* ctx) override;
  bool onPaste(Context* ctx, const gfx::Point* position) override;
  bool onClear(Context* ctx) override;
  void onCancel(Context* ctx) override;

protected:
  bool onProcessMessage(ui::Message* msg) override;

private:
  bool hasContentInActiveFrame(const doc::Layer* layer) const;

  Type m_type;
  Doc* m_document;
  ui::View* m_view;
  DocViewPreviewDelegate* m_previewDelegate;
  Editor* m_editor;
  gfx::Point m_timelineScroll;
};

} // namespace app

#endif
