/*
  *
  * This file is a part of libpaperde.
  * Library for handling various services related to Paper Desktop
  * Copyright 2020 CuboCore Group
  *
  *
  *
  * This file was originally a part of SmartVerticalFlowLayout project (https://github.com/VaysseB/SmartVerticalFlowLayout)
  * Suitable modifications have been done to meet the needs of Paper Desktop.
  *
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  *
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  *
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  *
  */

#pragma once

#include <QLayout>
#include <QRect>
#include <QStyle>

#include <paperde/paperglobals.h>

namespace Paper {
class DynamicLayout;
}

class LIBPAPER_DLLSPEC Paper::DynamicLayout : public QLayout
{
	Q_OBJECT

	Q_PROPERTY(int horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
	Q_PROPERTY(int verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
	Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment)
	Q_PROPERTY(int maxRowCount READ maxRowCount WRITE setMaxRowCount)

public:
	explicit DynamicLayout(QWidget *parent = nullptr);
	~DynamicLayout();

	int count() const override;
	void addItem(QLayoutItem *item) override;
	QLayoutItem *itemAt(int index) const override;
	QLayoutItem *takeAt(int index) override;

	int horizontalSpacing() const;
	int verticalSpacing() const;

	int maxRowCount() const;

	/**
	  * @brief Return with no expanding direction if alignment isn't justify nor 0.
	  * @return Qt::Horizontal or 0
	  */
	Qt::Orientations expandingDirections() const override;

	QSize sizeHint() const override;
	QSize minimumSize() const override;
	void setGeometry(const QRect& rect) override;
	bool hasHeightForWidth() const override;
	int heightForWidth(int width);

public slots:
	void setHorizontalSpacing(int space);
	void setVerticalSpacing(int space);

	void setMaxRowCount(int count);

	/**
	  * @brief Change alignment of all items.
	  * You must call DynamicLayout::updateLayout() if called as
	  * QLayout* or QLayoutItem* because the function isn't virtual
	  *
	  * @param align Items alignment (0, Justify, Left, Center, Right)
	  */
	void setAlignment(Qt::Alignment align);

	/**
	  * @brief Force layout to reprocess all items positions.
	  */
	void updateLayout();

private:
	void doLayout(const QRect& rect);
	int smartSpacing(QStyle::PixelMetric pm) const;

private:
	QList<QLayoutItem *> m_items;
	int m_hSpace;
	int m_vSpace;

	int m_maxRowCount;

	mutable QList<QList<QLayoutItem *> > m_structure;
	mutable QRect m_structureGeometry;
	mutable bool m_isLayoutModified;

private:
	Q_DISABLE_COPY(DynamicLayout)
};
