// Aseprite
// Copyright (C) 2019-2022  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_CMD_TRANSACTION_H_INCLUDED
#define APP_CMD_TRANSACTION_H_INCLUDED
#pragma once

#include "app/cmd_sequence.h"
#include "app/doc_range.h"
#include "app/sprite_position.h"

#include <memory>
#include <sstream>

namespace app {

  // Cmds created on each Transaction.
  // The whole DocUndo contains a list of these CmdTransaction.
  class CmdTransaction : public CmdSequence {
  public:
    CmdTransaction(const std::string& label,
                   bool changeSavedState);

    bool doesChangeSavedState() const { return m_changeSavedState; }

    // Moves the CmdTransaction internals to a new copy in case that
    // we want to rollback this CmdTransaction and start again with
    // the new CmdTransaction.
    CmdTransaction* moveToEmptyCopy();

    void setNewDocRange(const DocRange& range);
    void updateSpritePositionAfter();

    SpritePosition spritePositionBeforeExecute() const { return m_spritePositionBefore; }
    SpritePosition spritePositionAfterExecute() const { return m_spritePositionAfter; }

    std::istream* documentRangeBeforeExecute() const;
    std::istream* documentRangeAfterExecute() const;

  protected:
    void onExecute() override;
    void onUndo() override;
    void onRedo() override;
    std::string onLabel() const override;
    size_t onMemSize() const override;

  private:
    SpritePosition calcSpritePosition() const;
    bool isDocRangeEnabled() const;
    DocRange calcDocRange() const;

    struct Ranges {
      std::stringstream m_before;
      std::stringstream m_after;
    };

    SpritePosition m_spritePositionBefore;
    SpritePosition m_spritePositionAfter;
    std::unique_ptr<Ranges> m_ranges;
    std::string m_label;
    bool m_changeSavedState;
  };

} // namespace app

#endif
