/***************************************************************************
 *   Copyright (C) 2018 by Intevation GmbH <intevation@intevation.de>      *
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include "event_p.h"
#include <QApplication>

#include "../form.h"

using namespace Okular;

class Event::Private
{
public:
    Private(EventType eventType)
        : m_target(nullptr)
        , m_targetPage(nullptr)
        , m_source(nullptr)
        , m_sourcePage(nullptr)
        , m_eventType(eventType)
        , m_returnCode(false)
        , m_shiftModifier(false)
    {
    }

    void *m_target;
    Page *m_targetPage;
    FormField *m_source;
    Page *m_sourcePage;
    EventType m_eventType;
    QString m_targetName;
    QVariant m_value;
    bool m_returnCode;
    bool m_shiftModifier;
};

Event::Event()
    : d(new Private(UnknownEvent))
{
}

Event::Event(EventType eventType)
    : d(new Private(eventType))
{
}

Event::EventType Event::eventType() const
{
    return d->m_eventType;
}

QString Event::name() const
{
    switch (d->m_eventType) {
    case (FieldCalculate):
        return QStringLiteral("Calculate");
    case (FieldFormat):
        return QStringLiteral("Format");
    case (FieldKeystroke):
        return QStringLiteral("Keystroke");
    case (FieldFocus):
        return QStringLiteral("Focus");
    case (FieldValidate):
        return QStringLiteral("Validate");
    case (UnknownEvent):
    default:
        return QStringLiteral("Unknown");
    }
}

QString Event::type() const
{
    switch (d->m_eventType) {
    case (FieldCalculate):
    case (FieldFormat):
    case (FieldKeystroke):
    case (FieldFocus):
    case (FieldValidate):
        return QStringLiteral("Field");
    case (UnknownEvent):
    default:
        return QStringLiteral("Unknown");
    }
}

QString Event::targetName() const
{
    if (!d->m_targetName.isNull()) {
        return d->m_targetName;
    }

    return QStringLiteral("JavaScript for: ") + type() + name();
}

void Event::setTargetName(const QString &val)
{
    d->m_targetName = val;
}

FormField *Event::source() const
{
    return d->m_source;
}

void Event::setSource(FormField *val)
{
    d->m_source = val;
}

Page *Event::sourcePage() const
{
    return d->m_sourcePage;
}

void Event::setSourcePage(Page *val)
{
    d->m_sourcePage = val;
}

void *Event::target() const
{
    return d->m_target;
}

void Event::setTarget(void *target)
{
    d->m_target = target;
}

Page *Event::targetPage() const
{
    return d->m_targetPage;
}

void Event::setTargetPage(Page *val)
{
    d->m_targetPage = val;
}

QVariant Event::value() const
{
    return d->m_value;
}

void Event::setValue(const QVariant &val)
{
    d->m_value = val;
}

bool Event::returnCode() const
{
    return d->m_returnCode;
}

void Event::setReturnCode(bool returnCode)
{
    d->m_returnCode = returnCode;
}

bool Event::shiftModifier() const
{
    return d->m_shiftModifier;
}

void Event::setShiftModifier(bool shiftModifier)
{
    d->m_shiftModifier = shiftModifier;
}

// static
std::shared_ptr<Event> Event::createFormCalculateEvent(FormField *target, Page *targetPage, FormField *source, Page *sourcePage, const QString &targetName)
{
    std::shared_ptr<Event> ret(new Event(Event::FieldCalculate));
    ret->setSource(source);
    ret->setSourcePage(sourcePage);
    ret->setTarget(target);
    ret->setTargetPage(targetPage);
    ret->setTargetName(targetName);

    FormFieldText *fft = dynamic_cast<FormFieldText *>(target);
    if (fft) {
        ret->setValue(QVariant(fft->text()));
    }
    return ret;
}

// static
std::shared_ptr<Event> Event::createFormatEvent(FormField *target, Page *targetPage, const QString &targetName)
{
    std::shared_ptr<Event> ret(new Event(Event::FieldFormat));
    ret->setTarget(target);
    ret->setTargetPage(targetPage);
    ret->setTargetName(targetName);

    FormFieldText *fft = dynamic_cast<FormFieldText *>(target);
    if (fft) {
        ret->setValue(QVariant(fft->text()));
    }
    return ret;
}

// static
std::shared_ptr<Event> Event::createKeystrokeEvent(FormField *target, Page *targetPage)
{
    std::shared_ptr<Event> ret(new Event(Event::FieldKeystroke));
    ret->setTarget(target);
    ret->setTargetPage(targetPage);

    FormFieldText *fft = dynamic_cast<FormFieldText *>(target);
    if (fft) {
        ret->setReturnCode(true);
        ret->setValue(QVariant(fft->text()));
    }
    return ret;
}

std::shared_ptr<Event> Event::createFormFocusEvent(FormField *target, Page *targetPage, const QString &targetName)
{
    std::shared_ptr<Event> ret(new Event(Event::FieldFocus));
    ret->setTarget(target);
    ret->setTargetPage(targetPage);
    ret->setTargetName(targetName);
    ret->setShiftModifier(QApplication::keyboardModifiers() & Qt::ShiftModifier);

    FormFieldText *fft = dynamic_cast<FormFieldText *>(target);
    if (fft) {
        ret->setValue(QVariant(fft->text()));
    }
    return ret;
}

std::shared_ptr<Event> Event::createFormValidateEvent(FormField *target, Page *targetPage, const QString &targetName)
{
    std::shared_ptr<Event> ret(new Event(Event::FieldValidate));
    ret->setTarget(target);
    ret->setTargetPage(targetPage);
    ret->setTargetName(targetName);
    ret->setShiftModifier(QApplication::keyboardModifiers() & Qt::ShiftModifier);

    FormFieldText *fft = dynamic_cast<FormFieldText *>(target);
    if (fft) {
        ret->setValue(QVariant(fft->text()));
        ret->setReturnCode(true);
    }
    return ret;
}
