/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include "fields.h"
#include <algorithm>
#include <QtDebug>
#include <poppler-form.h>
#include <util/sll/unreachable.h>
#include "links.h"

namespace LeechCraft
{
namespace Monocle
{
namespace PDF
{
	FormField::FormField (std::shared_ptr<Poppler::FormField> field)
	: BaseField_ (field)
	{
	}

	int FormField::GetID () const
	{
		return BaseField_->id ();
	}

	QRectF FormField::GetRect () const
	{
		return BaseField_->rect ();
	}

	QString FormField::GetName () const
	{
		return BaseField_->uiName ();
	}

	FormFieldText::FormFieldText (std::shared_ptr<Poppler::FormField> field)
	: FormField (field)
	, Field_ (std::dynamic_pointer_cast<Poppler::FormFieldText> (field))
	{
	}

	FormType FormFieldText::GetType () const
	{
		return FormType::Text;
	}

	Qt::Alignment FormFieldText::GetAlignment () const
	{
		return Field_->textAlignment ();
	}

	QString FormFieldText::GetText () const
	{
		return Field_->text ();
	}

	void FormFieldText::SetText (const QString& text)
	{
		Field_->setText (text);
	}

	auto FormFieldText::GetTextType () const -> Type
	{
		switch (Field_->textType ())
		{
		case Poppler::FormFieldText::Normal:
			return Type::SingleLine;
		case Poppler::FormFieldText::Multiline:
			return Type::Multiline;
		case Poppler::FormFieldText::FileSelect:
			return Type::File;
		}

		Util::Unreachable ();
	}

	int FormFieldText::GetMaximumLength () const
	{
		return Field_->maximumLength ();
	}

	bool FormFieldText::IsPassword () const
	{
		return Field_->isPassword ();
	}

	bool FormFieldText::IsRichText () const
	{
		return Field_->isRichText ();
	}

	FormFieldChoice::FormFieldChoice (std::shared_ptr<Poppler::FormField> field)
	: FormField (field)
	, Field_ (std::dynamic_pointer_cast<Poppler::FormFieldChoice> (field))
	{
	}

	FormType FormFieldChoice::GetType () const
	{
		return FormType::Choice;
	}

	Qt::Alignment FormFieldChoice::GetAlignment () const
	{
		return Field_->textAlignment ();
	}

	auto FormFieldChoice::GetChoiceType () const -> Type
	{
		switch (Field_->choiceType ())
		{
		case Poppler::FormFieldChoice::ComboBox:
			return Type::Combobox;
		case Poppler::FormFieldChoice::ListBox:
			return Type::ListBox;
		}

		qWarning () << Q_FUNC_INFO
				<< "unknown choice type"
				<< Field_->choiceType ();
		return Type::Combobox;
	}

	QStringList FormFieldChoice::GetAllChoices () const
	{
		return Field_->choices ();
	}

	QList<int> FormFieldChoice::GetCurrentChoices () const
	{
		return Field_->currentChoices ();
	}

	void FormFieldChoice::SetCurrentChoices (const QList<int>& choices)
	{
		Field_->setCurrentChoices (choices);
	}

	QString FormFieldChoice::GetEditChoice () const
	{
		return Field_->editChoice ();
	}

	void FormFieldChoice::SetEditChoice (const QString& choice)
	{
		Field_->setEditChoice (choice);
	}

	bool FormFieldChoice::IsEditable () const
	{
		return Field_->isEditable ();
	}

	FormFieldButton::FormFieldButton (std::shared_ptr<Poppler::FormField> field, Document *doc)
	: FormField (field)
	, Field_ (std::dynamic_pointer_cast<Poppler::FormFieldButton> (field))
	, Doc_ (doc)
	, ButtonGroup_ (Field_->siblings ())
	{
		if (!ButtonGroup_.isEmpty ())
		{
			ButtonGroup_ << GetID ();
			std::sort (ButtonGroup_.begin (), ButtonGroup_.end ());
		}
	}

	FormType FormFieldButton::GetType () const
	{
		return FormType::Button;
	}

	Qt::Alignment FormFieldButton::GetAlignment () const
	{
		return Qt::AlignLeft;
	}

	auto FormFieldButton::GetButtonType () const -> Type
	{
		switch (Field_->buttonType ())
		{
		case Poppler::FormFieldButton::Push:
			return Type::Pushbutton;
		case Poppler::FormFieldButton::CheckBox:
			return Type::Checkbox;
		case Poppler::FormFieldButton::Radio:
			return Type::Radiobutton;
		}

		qWarning () << Q_FUNC_INFO
				<< "unknown button type"
				<< Field_->buttonType ();
		return Type::Pushbutton;
	}

	QString FormFieldButton::GetCaption () const
	{
		if (!Field_->caption ().isEmpty ())
			return Field_->caption ();
		if (!Field_->uiName ().isEmpty ())
			return Field_->uiName ();
		return Field_->name ();
	}

	bool FormFieldButton::IsChecked () const
	{
		return Field_->state ();
	}

	void FormFieldButton::SetChecked (bool checked)
	{
		Field_->setState (checked);
	}

	QList<int> FormFieldButton::GetButtonGroup () const
	{
		return ButtonGroup_;
	}

	void FormFieldButton::HandleActivated ()
	{
		auto actLink = Field_->activationAction ();
		if (!actLink)
			return;

		ILink_ptr link (new Link (Doc_, actLink));
		link->Execute ();
	}
}
}
}
