// Aseprite Document Library
// Copyright (c) 2023 Igara Studio S.A.
// Copyright (c) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifndef DOC_CELS_RANGE_H_INCLUDED
#define DOC_CELS_RANGE_H_INCLUDED
#pragma once

#include "doc/cel_list.h"
#include "doc/frame.h"
#include "doc/object_id.h"
#include "doc/selected_frames.h"

#include <set>

namespace doc {

class Cel;
class Layer;
class SelectedFrames;
class Sprite;

class CelsRange {
public:
  enum Flags {
    ALL,
    UNIQUE,
  };

  CelsRange(const Sprite* sprite, const SelectedFrames& selFrames, const Flags flags = ALL);

  class iterator {
  public:
    typedef Cel* value_type;
    typedef std::ptrdiff_t difference_type;
    typedef Cel** pointer;
    typedef Cel*& reference;
    typedef std::forward_iterator_tag iterator_category;

    iterator(const SelectedFrames& selFrames);
    iterator(const Sprite* sprite, const SelectedFrames& selFrames, const Flags flags);

    bool operator==(const iterator& other) const { return m_cel == other.m_cel; }

    bool operator!=(const iterator& other) const { return !operator==(other); }

    Cel* operator*() const { return m_cel; }

    iterator& operator++();

  private:
    Cel* m_cel;
    const SelectedFrames& m_selFrames;
    frames::const_iterator m_frameIterator;
    Flags m_flags;
    std::set<ObjectId> m_visited;
  };

  iterator begin() { return m_begin; }
  iterator end() { return m_end; }

  int size()
  {
    int count = 0;
    for (auto it = begin(), e = end(); it != e; ++it)
      ++count;
    return count;
  }

  // Converts the CelsRange into a CelList (which indeed it's an
  // array).
  CelList toList();

private:
  SelectedFrames m_selFrames;
  iterator m_begin, m_end;
};

} // namespace doc

#endif
