/*
  Copyright (c) 2012-2015 Montel Laurent <montel@kde.org>

  This library is free software; you can redistribute it and/or modify it
  under the terms of the GNU Library General Public License as published by
  the Free Software Foundation; either version 2 of the License, or (at your
  option) any later version.

  This library 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 Library General Public
  License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

*/

#include "composerview.h"
#include "private/composerview_p.h"

#include "table/composertableactionmenu.h"
#include "globalsettings_base.h"

#include <kpimtextedit/emoticontexteditaction.h>


#include <KLocalizedString>
#include <KAction>
#include <KToggleAction>
#include <KFontAction>
#include <KSelectAction>
#include <KActionCollection>
#include <KMessageBox>
#include <KStandardDirs>
#include <KDebug>
#include <KMenu>
#include <KToolBar>

#include <QAction>
#include <QFileInfo>
#include <QWebElement>
#include <QContextMenuEvent>
#include <QDebug>

namespace ComposerEditorNG {

ComposerView::ComposerView(QWidget *parent)
    : KWebView(parent),
      d(new ComposerViewPrivate(this))
{
    QFile file ( initialHtml() );
    kDebug() <<file.fileName();

    if ( !file.open ( QIODevice::ReadOnly ) )
        KMessageBox::error(this, i18n ( "Cannot open template file %1.", QFileInfo(file).absoluteFilePath() ), i18n ( "composer editor" ));
    else
        setContent ( file.readAll());//, "application/xhtml+xml" );

    page()->setContentEditable(true);
    page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
    connect(this, SIGNAL(linkClicked(QUrl)), SIGNAL(openLink(QUrl)));
    connect(page(), SIGNAL(selectionChanged()), this, SLOT(_k_slotAdjustActions()) );

    setWindowModified(false);
}

ComposerView::~ComposerView()
{
    delete d;
}

QString ComposerView::initialHtml()
{
    return KStandardDirs::locate ( "data", QLatin1String("composereditor/composereditorinitialhtml") );
}

void ComposerView::createActions(const QList<ComposerViewAction>& lstActions)
{
    Q_FOREACH (ComposerViewAction action, lstActions)
        d->createAction( action );

    d->connectActionGroup();
}

void ComposerView::createAllActions()
{
    for (uint i=0;i<LastType;++i)
        d->createAction( (ComposerViewAction)i );
    d->connectActionGroup();
}


void ComposerView::addCreatedActionsToActionCollection(KActionCollection *actionCollection)
{
    if (actionCollection) {
        if (d->action_text_bold)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_bold"), d->action_text_bold);
        if (d->action_text_italic)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_italic"), d->action_text_italic);
        if (d->action_text_underline)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_underline"), d->action_text_underline);
        if (d->action_text_strikeout)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_strikeout"), d->action_text_strikeout);
        if (d->action_align_left)
            actionCollection->addAction(QLatin1String("htmleditor_format_align_left"), d->action_align_left);
        if (d->action_align_center)
            actionCollection->addAction(QLatin1String("htmleditor_format_align_center"), d->action_align_center);
        if (d->action_align_right)
            actionCollection->addAction(QLatin1String("htmleditor_format_align_right"), d->action_align_right);
        if (d->action_align_justify)
            actionCollection->addAction(QLatin1String("htmleditor_format_align_justify"), d->action_align_justify);
        if (d->action_direction_ltr)
            actionCollection->addAction(QLatin1String("htmleditor_direction_ltr"), d->action_direction_ltr);
        if (d->action_direction_rtl)
            actionCollection->addAction(QLatin1String("htmleditor_direction_rtl"), d->action_direction_rtl);
        if (d->action_text_subscript)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_subscript"), d->action_text_subscript);
        if (d->action_text_superscript)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_superscript"), d->action_text_superscript);
        if (d->action_page_color)
            actionCollection->addAction( QLatin1String( "htmleditor_page_color_and_background" ), d->action_page_color );
        if (d->action_insert_table)
            actionCollection->addAction( QLatin1String( "htmleditor_insert_new_table" ), d->action_insert_table );
        if (d->action_insert_link)
            actionCollection->addAction(QLatin1String("htmleditor_insert_link"), d->action_insert_link);
        if (d->action_insert_horizontal_rule)
            actionCollection->addAction(QLatin1String("htmleditor_insert_horizontal_rule"), d->action_insert_horizontal_rule);
        if (d->action_text_foreground_color)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_foreground_color"), d->action_text_foreground_color);
        if (d->action_text_background_color)
            actionCollection->addAction(QLatin1String("htmleditor_format_text_background_color"), d->action_text_background_color);
        if (d->action_add_emoticon)
            actionCollection->addAction(QLatin1String("htmleditor_add_emoticon"), d->action_add_emoticon);
        if (d->action_insert_html)
            actionCollection->addAction( QLatin1String( "htmleditor_insert_html" ), d->action_insert_html);
        if (d->action_insert_image)
            actionCollection->addAction( QLatin1String( "htmleditor_add_image" ), d->action_insert_image);
        if (d->action_spell_check)
            actionCollection->addAction(QLatin1String("htmleditor_spell_check"), d->action_spell_check);
        if (d->action_format_reset)
            actionCollection->addAction( QLatin1String("htmleditor_format_reset"), d->action_format_reset);
        if (d->action_font_family)
            actionCollection->addAction(QLatin1String("htmleditor_format_font_family"), d->action_font_family);
        if (d->action_font_size)
            actionCollection->addAction(QLatin1String("htmleditor_format_font_size"), d->action_font_size);
        if (d->action_format_type)
            actionCollection->addAction(QLatin1String("htmleditor_format_type"), d->action_format_type);
        if (d->action_block_quote)
            actionCollection->addAction(QLatin1String("htmleditor_block_quote"), d->action_block_quote);
        if (d->action_ordered_list)
            actionCollection->addAction(QLatin1String("htmleditor_format_list_ordered"), d->action_ordered_list);
        if (d->action_unordered_list)
            actionCollection->addAction(QLatin1String("htmleditor_format_list_unordered"), d->action_unordered_list);
        if (d->action_list_indent)
            actionCollection->addAction(QLatin1String("htmleditor_format_list_indent_more"), d->action_list_indent);
        if (d->action_list_dedent)
            actionCollection->addAction(QLatin1String("htmleditor_format_list_indent_less"), d->action_list_dedent);
        if (d->action_find)
            actionCollection->addAction(QLatin1String("htmleditor_find"), d->action_find);
        if (d->action_replace)
            actionCollection->addAction(QLatin1String("htmleditor_replace"), d->action_replace);
        if (d->action_save_as)
            actionCollection->addAction(QLatin1String("htmleditor_save_as"), d->action_save_as);
        if (d->action_print)
            actionCollection->addAction(QLatin1String("htmleditor_print"), d->action_print);
        if (d->action_print_preview)
            actionCollection->addAction(QLatin1String("htmleditor_print_preview"), d->action_print_preview);
        if (d->action_paste_withoutformatting)
            actionCollection->addAction(QLatin1String("htmleditor_paste_without_formatting"), d->action_paste_withoutformatting);
        if (d->action_insert_specialchar)
            actionCollection->addAction(QLatin1String("htmleditor_insert_specialchar"), d->action_insert_specialchar);
        if (d->action_insert_anchor)
            actionCollection->addAction(QLatin1String("htmleditor_insert_anchor"), d->action_insert_anchor);
    }
}

void ComposerView::contextMenuEvent(QContextMenuEvent *event)
{
    d->hideImageResizeWidget();
    d->contextMenuResult = page()->mainFrame()->hitTestContent(event->pos());

    const bool linkSelected = !d->contextMenuResult.linkElement().isNull();
    const bool imageSelected = !d->contextMenuResult.imageUrl().isEmpty();

    const QWebElement elm = d->contextMenuResult.element();
    const bool tableCellSelected = (elm.tagName().toLower() == QLatin1String("td"));
    const bool tableSelected = (elm.tagName().toLower() == QLatin1String("table") ||
                                tableCellSelected );

    const bool listSelected = (elm.tagName().toLower() == QLatin1String("ol") ||
                               elm.tagName().toLower() == QLatin1String("ul") ||
                               elm.tagName().toLower() == QLatin1String("li") );

    const bool anchorSelected = (elm.tagName().toLower() == QLatin1String("a"));

    kDebug()<<" elm.tagName().toLower() "<<elm.tagName().toLower();

    KMenu *menu = new KMenu;
    const QString selectedText = page()->mainFrame()->toPlainText().simplified();
    const bool emptyDocument = selectedText.isEmpty();

    menu->addAction(page()->action(QWebPage::Undo));
    menu->addAction(page()->action(QWebPage::Redo));
    menu->addSeparator();
    menu->addAction(page()->action(QWebPage::Cut));
    menu->addAction(page()->action(QWebPage::Copy));
    menu->addAction(page()->action(QWebPage::Paste));
    if (d->action_paste_withoutformatting)
        menu->addAction(d->action_paste_withoutformatting);

    menu->addSeparator();
    if (!emptyDocument) {
        menu->addAction(page()->action(QWebPage::SelectAll));
        menu->addSeparator();
    }
    if (!emptyDocument && d->action_find) {
        menu->addAction(d->action_find);
        menu->addSeparator();
    }
    if (imageSelected) {
        QAction *editImageAction = menu->addAction(i18n("Edit Image..."));
        connect( editImageAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotEditImage()) );
    } else if (linkSelected) {
        QAction *editLinkAction = menu->addAction(i18n("Edit Link..."));
        connect( editLinkAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotEditLink()) );
        QAction *openLinkAction = menu->addAction(i18n("Open Link"));
        connect( openLinkAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotOpenLink()) );
    } else if (tableSelected) {
        ComposerTableActionMenu * tableActionMenu = new ComposerTableActionMenu(elm,menu,this);
        connect(tableActionMenu, SIGNAL(insertNewTable()), this, SLOT(_k_slotInsertTable()));
        menu->addAction(tableActionMenu);
    } else if (listSelected) {
        QAction *editListAction = menu->addAction(i18n("Edit List..."));
        connect( editListAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotEditList()) );
    }
    menu->addSeparator();
    if (!emptyDocument && d->action_spell_check) {
        menu->addAction(d->action_spell_check);
        menu->addSeparator();
    }
#if QTWEBKIT_VERSION >= QTWEBKIT_VERSION_CHECK(2, 3, 0)
    //Don't use "Auto Spell Check" it will confict with search menu entry in spellchecklineedit.
    QAction *autoSpellCheckingAction = menu->addAction(i18n("Enable Spell Checking"));
    autoSpellCheckingAction->setCheckable( true );
    autoSpellCheckingAction->setChecked( d->checkSpellingEnabled() );
    connect( autoSpellCheckingAction, SIGNAL(triggered(bool)), this, SLOT(_k_changeAutoSpellChecking(bool)) );
#endif
    QAction *speakAction = menu->addAction(i18n("Speak Text"));
    speakAction->setIcon(KIcon(QLatin1String("preferences-desktop-text-to-speech")));
    speakAction->setEnabled(!emptyDocument );
    connect( speakAction, SIGNAL(triggered(bool)), this, SLOT(_k_slotSpeakText()) );
    addExtraAction(menu);
    menu->exec(event->globalPos());
    delete menu;
}

void ComposerView::addExtraAction(QMenu *menu)
{
    Q_UNUSED(menu);
    //Redefine if necessary.
}

void ComposerView::setActionsEnabled(bool enabled)
{
    Q_FOREACH (QAction *action, d->htmlEditorActionList)
        action->setEnabled(enabled);
}

void ComposerView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        d->contextMenuResult = page()->mainFrame()->hitTestContent(event->pos());
        const bool imageSelected = !d->contextMenuResult.imageUrl().isEmpty();
        if (imageSelected) {
            d->showImageResizeWidget();
        }
    } else {
        d->hideImageResizeWidget();
    }
    KWebView::mousePressEvent(event);
}

void ComposerView::keyPressEvent(QKeyEvent *event)
{
    d->hideImageResizeWidget();
    KWebView::keyPressEvent(event);
}

void ComposerView::wheelEvent(QWheelEvent *event)
{
    d->hideImageResizeWidget();
    KWebView::wheelEvent(event);
}

void ComposerView::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        d->contextMenuResult = page()->mainFrame()->hitTestContent(event->pos());
        const bool imageSelected = !d->contextMenuResult.imageUrl().isEmpty();
        if (imageSelected) {
            d->showImageResizeWidget();
            d->_k_slotEditImage();
        }
    } else {
        d->hideImageResizeWidget();
    }
    KWebView::mouseDoubleClickEvent(event);
}

void ComposerView::setHtmlContent( const QString &html )
{
    setHtml(html);
}

void ComposerView::evaluateJavascript( const QString &javascript)
{
    d->evaluateJavascript(javascript);
}

void ComposerView::createToolBar(const QList<ComposerViewAction> &lstAction, KToolBar *toolbar)
{
    const int numberOfAction(lstAction.count());
    for (int i=0;i<numberOfAction;++i) {
        switch(lstAction.at(i)) {
        case Bold:
            toolbar->addAction(d->action_text_bold);
            break;
        case Italic:
            toolbar->addAction(d->action_text_italic);
            break;
        case Underline:
            toolbar->addAction(d->action_text_underline);
            break;
        case StrikeOut:
            toolbar->addAction(d->action_text_strikeout);
            break;
        case AlignLeft:
            toolbar->addAction(d->action_align_left);
            break;
        case AlignCenter:
            toolbar->addAction(d->action_align_center);
            break;
        case AlignRight:
            toolbar->addAction(d->action_align_right);
            break;
        case AlignJustify:
            toolbar->addAction(d->action_align_justify);
            break;
        case DirectionLtr:
            toolbar->addAction(d->action_direction_ltr);
            break;
        case DirectionRtl:
            toolbar->addAction(d->action_direction_rtl);
            break;
        case SubScript:
            toolbar->addAction(d->action_text_subscript);
            break;
        case SuperScript:
            toolbar->addAction(d->action_text_superscript);
            break;
        case HorizontalRule:
            toolbar->addAction(d->action_insert_horizontal_rule);
            break;
        case ListIndent:
            toolbar->addAction(d->action_list_indent);
            break;
        case ListDedent:
            toolbar->addAction(d->action_list_dedent);
            break;
        case OrderedList:
            toolbar->addAction(d->action_ordered_list);
            break;
        case UnorderedList:
            toolbar->addAction(d->action_unordered_list);
            break;
        case FormatType:
            toolbar->addAction(d->action_format_type);
            break;
        case FontSize:
            toolbar->addAction(d->action_font_size);
            break;
        case FontFamily:
            toolbar->addAction(d->action_font_family);
            break;
        case Emoticon:
            toolbar->addAction(d->action_add_emoticon);
            break;
        case InsertHtml:
            toolbar->addAction(d->action_insert_html);
            break;
        case InsertImage:
            toolbar->addAction(d->action_insert_image);
            break;
        case InsertTable:
            toolbar->addAction(d->action_insert_table);
            break;
        case InsertLink:
            toolbar->addAction(d->action_insert_link);
            break;
        case InsertSpecialChar:
            toolbar->addAction(d->action_insert_specialchar);
            break;
        case TextForegroundColor:
            toolbar->addAction(d->action_text_foreground_color);
            break;
        case TextBackgroundColor:
            toolbar->addAction(d->action_text_background_color);
            break;
        case FormatReset:
            toolbar->addAction(d->action_format_reset);
            break;
        case SpellCheck:
            toolbar->addAction(d->action_spell_check);
            break;
        case Find:
            toolbar->addAction(d->action_find);
            break;
        case Replace:
            toolbar->addAction(d->action_replace);
            break;
        case PageColor:
            toolbar->addAction(d->action_page_color);
            break;
        case BlockQuote:
            toolbar->addAction(d->action_block_quote);
            break;
        case SaveAs:
            toolbar->addAction(d->action_save_as);
            break;
        case Print:
            toolbar->addAction(d->action_print);
            break;
        case PrintPreview:
            toolbar->addAction(d->action_print_preview);
            break;
        case Separator: {
            QAction *act = new QAction(this);
            act->setSeparator(true);
            toolbar->addAction(act);
            break;
        }
        case PasteWithoutFormatting: {
            toolbar->addAction(d->action_paste_withoutformatting);
            break;
        }
        case InsertAnchor: {
            toolbar->addAction(d->action_insert_anchor);
            break;
        }
        case LastType: {
            //nothing
            break;
        }
        }
    }
}

QAction *ComposerView::action(ComposerViewAction actionType) const
{
    switch(actionType) {
    case Bold:
        return d->action_text_bold;
    case Italic:
        return d->action_text_italic;
    case Underline:
        return d->action_text_underline;
    case StrikeOut:
        return d->action_text_strikeout;
    case AlignLeft:
        return d->action_align_left;
    case AlignCenter:
        return d->action_align_center;
    case AlignRight:
        return d->action_align_right;
    case AlignJustify:
        return d->action_align_justify;
    case DirectionLtr:
        return d->action_direction_ltr;
    case DirectionRtl:
        return d->action_direction_rtl;
    case SubScript:
        return d->action_text_subscript;
    case SuperScript:
        return d->action_text_superscript;
    case HorizontalRule:
        return d->action_insert_horizontal_rule;
    case ListIndent:
        return d->action_list_indent;
    case ListDedent:
        return d->action_list_dedent;
    case OrderedList:
        return d->action_ordered_list;
    case UnorderedList:
        return d->action_unordered_list;
    case FormatType:
        return d->action_format_type;
    case FontSize:
        return d->action_font_size;
    case FontFamily:
        return d->action_font_family;
    case Emoticon:
        return d->action_add_emoticon;
    case InsertHtml:
        return d->action_insert_html;
    case InsertImage:
        return d->action_insert_image;
    case InsertTable:
        return d->action_insert_table;
    case InsertLink:
        return d->action_insert_link;
    case InsertSpecialChar:
        return d->action_insert_specialchar;
    case TextForegroundColor:
        return d->action_text_foreground_color;
    case TextBackgroundColor:
        return d->action_text_background_color;
    case FormatReset:
        return d->action_format_reset;
    case SpellCheck:
        return d->action_spell_check;
    case Find:
        return d->action_find;
    case Replace:
        return d->action_replace;
    case PageColor:
        return d->action_page_color;
    case BlockQuote:
        return d->action_block_quote;
    case SaveAs:
        return d->action_save_as;
    case Print:
        return d->action_print;
    case PrintPreview:
        return d->action_print_preview;
    case PasteWithoutFormatting:
        return d->action_paste_withoutformatting;
    case InsertAnchor:
        return d->action_insert_anchor;
    case Separator:
    case LastType:
        break;
    }
    return 0;
}

QMap<QString, QString> ComposerView::localImages() const
{
    return d->localImages();
}


}

#include "moc_composerview.cpp"
