/***************************************************************************
 *   Copyright (C) 2003-2005 by liuspider                                  *
 *   liuspider@users.sourceforge.net                                       *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#define USE_SCIM_KDE_SETTINGS
#include "inputwindow.h"

#include "scimlookuptable.h"
#include "scimlineedit.h"
#include "scimdragableframe.h"
#include "src/skimglobalactions.h"

#include <qlineedit.h>
#include "scimstringlistitem.h"
#include <kdebug.h>
#include <kiconloader.h>

#define TOP_LEVEL_WFLAGS \
   Qt::WStyle_Customize|Qt::WStyle_NoBorder|Qt::WStyle_StaysOnTop|Qt::WX11BypassWM|Qt::WStyle_Tool

inputWindow::inputWindow( SkimPluginManager* is, QWidget* parent, const char* name, WFlags fl )
    : ScimDragableFrame( parent, parent, name, fl )
{
    allModules = is;
    InputServer = allModules->getInputServer();
    
    setLineWidth(0);
    setMidLineWidth(0);
//     setFrameStyle( QFrame::Box | QFrame::Sunken );

    ScreenRect = QApplication::desktop()->screenGeometry();
    if ( !name )
      setName( "inputWindow" );
    setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, 0, 0) );
    inputWindowLayout = new QVBoxLayout( this, 0, 1, "inputWindowLayout");
    inputWindowLayout->setResizeMode( QLayout::FreeResize );

    PreEditText = new ScimLineEdit( this, "PreEditText" );
    PreEditText->setLineWidth(1);
    PreEditText->setMidLineWidth(0);
    PreEditText->setFrameStyle( QFrame::Box | QFrame::Sunken );
    PreEditText->hide();
    PreEditText->setBackgroundOrigin( QLineEdit::AncestorOrigin );
    PreEditText->setMouseTracking( FALSE );
    PreEditText->setAcceptDrops( FALSE );
    inputWindowLayout->addWidget( PreEditText );
    
    AuxText = new ScimStringListItem(this);
    AuxText->setLineWidth(1);
    AuxText->setMidLineWidth(0);
    AuxText->setFrameStyle( QFrame::Box | QFrame::Sunken );
//     AuxText->setFrameShadow( QFrame::Raised );
    inputWindowLayout->addWidget( AuxText );
    AuxText->hide();

    LookupLbl = new ScimLookupTable( this, inputWindowLayout, "LookupLbl",
      ScimKdeSettings::lookupTable_IsVertical());
    LookupLbl->setEnableMouse(ScimKdeSettings::enableMouse_IW());
    LookupLbl->setEnableHighlight(ScimKdeSettings::highlight_Candidate());
    LookupLbl->setLineWidth(1);
    LookupLbl->setMidLineWidth(0);
    LookupLbl->setFrameStyle( QFrame::Box | QFrame::Sunken );

    inputWindowLayout->addWidget( LookupLbl );
    
    languageChange();
    clearWState( WState_Polished );

    // signals and slots connections
    connect( LookupLbl, SIGNAL( previousPageRequested() ), InputServer, SLOT( lookupTablePageUp() ) );
    connect( LookupLbl, SIGNAL( nextPageRequested() ), InputServer, SLOT( lookupTablePageDown() ) );

    connect( InputServer, SIGNAL( updatePreeditStringReq(const QString &, const scim::AttributeList &) ),
        this, SLOT( updatePreeditString(const QString &, const scim::AttributeList & ) ) );
    connect( InputServer, 
        SIGNAL(updateLookupTableReq(const QStringList&, const QStringList&, 
            QValueList< scim :: AttributeList >&, int, int, scim::uint32, size_t & )),
        SLOT( updateLookupTable(const QStringList&, const QStringList&, 
            QValueList< scim :: AttributeList >&, int, int, scim::uint32, size_t & ) ) );
    connect( InputServer, SIGNAL( updateAuxStringReq(const QString &, const scim::AttributeList & ) ),
        this, SLOT(updateAuxString(const QString &, const scim::AttributeList & ) ) );
        
    connect( InputServer, SIGNAL( showAuxStringReq() ), this, SLOT( showAuxString() ) );
    connect( InputServer, SIGNAL( hideAuxStringReq() ), this, SLOT( hideAuxString() ) );
    connect( InputServer, SIGNAL( showLookupTableReq() ), this, SLOT( showLookupTable() ) );
    connect( InputServer, SIGNAL( showPreeditStringReq() ), this, SLOT( showPreeditString() ) );
    connect( InputServer, SIGNAL( hidePreeditStringReq() ), this, SLOT( hidePreeditString() ) );
    connect( InputServer, SIGNAL( hideLookupTableReq() ),
        this, SLOT( hideLookupTable() ) );
    connect( InputServer, SIGNAL( updateSpotLocationReq( int, int ) ),
        this, SLOT( updateSpotLocation( int, int ) ) );
    connect( InputServer, SIGNAL(updatePreeditCaretReq(int ) ),
        PreEditText, SLOT(setCursorPosition ( int )));
//     connect( InputServer, SIGNAL( turnOnPanelReq() ), this, SLOT( show() ) );
    connect( InputServer, SIGNAL( turnOffPanelReq() ), this, SLOT( hide() ) );

    connect( LookupLbl, SIGNAL(itemSelected(int )), InputServer, SLOT(selectLookupTableItem(int )));
    
    StickAction =
        static_cast<KToggleAction*>(allModules->getActionCollection()->action( "stick_inputwindow" ));
//     kdDebug(18010) << k_lineinfo << (int) StickAction << "\n";
//     if(StickAction)
//         connect(StickAction, SIGNAL(activated()), SLOT(toggleSticky()) );
                    
    changeSetting();
}

inputWindow::~inputWindow(){
    ScimKdeSettings::setIs_Sticky(sticky);
}

void inputWindow::toggleStick()
{
    static KIconLoader * kil = KGlobal::iconLoader();
    StickAction->setIconSet( kil->loadIcon( StickAction->isChecked() ? "pin_down": "pin_up", KIcon::User) );
    sticky = StickAction->isChecked();
}
void inputWindow::changeSetting()
{
//     kdDebug(18010) << k_lineinfo << " inputWindow::changeSetting()\n";
    LookupLbl->setVertical(ScimKdeSettings::lookupTable_IsVertical());
    if(!ScimKdeSettings::iW_Font().isEmpty())
    {
      QFont customFont;
      customFont.fromString(ScimKdeSettings::iW_Font());
      if(customFont != font())
        setFont(customFont);
    } else
      unsetFont();
    
    LookupLbl->setEnableMouse(ScimKdeSettings::enableMouse_IW());
    LookupLbl->setEnableHighlight(ScimKdeSettings::highlight_Candidate());
    
    sticky = ScimKdeSettings::is_Sticky();
    StickAction->setChecked(sticky);
    toggleStick();
}

void inputWindow::languageChange()
{
}

void inputWindow::updateAuxString( const QString & aux, const scim::AttributeList & attrs)
{
  AuxText->setText( aux, attrs );
}

void inputWindow::showAuxString()
{
  AuxText->show();
  if( !isVisible() )
      show();
  adjustSize();
}

void inputWindow::hideAuxString()
{
  AuxText->hide();
  adjustSize();
}

void inputWindow::updateSpotLocation( int x, int y )
{
    if(sticky) return;

    move( x, y );
}
void inputWindow::updatePreeditString( const QString & newprestr, const scim::AttributeList & atl)
{
    PreEditText->setText( newprestr, atl );
    adjustSize();
}

void inputWindow::hidePreeditString()
{
    PreEditText->hide();
    adjustSize();
}
void inputWindow::showPreeditString()
{
    PreEditText->show();
    if( !isVisible() )
      show();
    adjustSize();
}
void inputWindow::updateLookupTable( const QStringList& labellist, 
                                     const QStringList& lookupstringlist, 
                                     QValueList<scim::AttributeList > & attrslist,
                                     int cursor, int page_start,
                                     scim::uint32 candidates, size_t & exact_item_num)
{
    //the line below should be called after updateContent, but now it's a ugly hack
    //to push_front a highlight attribute to the attrslist
    LookupLbl->updateHighlight( cursor );

    exact_item_num = LookupLbl->updateContent(labellist, lookupstringlist, attrslist);
    LookupLbl->enablePreviousPage(page_start);
    LookupLbl->enableNextPage(page_start + exact_item_num < candidates);
//     LookupLbl->updateHighlight( currentHighlight );
    adjustSize();
}
void inputWindow::adjustSize()
{
    if(!PreEditText->isVisible() && !LookupLbl->isVisible() && !AuxText->isVisible())
    {
      hide();
      return;
    }
    
    ScimDragableFrame::adjustSize();
}
void inputWindow::hideLookupTable()
{
    LookupLbl->hide();
    adjustSize();
}
void inputWindow::showLookupTable()
{
    LookupLbl->show();
    if( !isVisible() )
      show();
    adjustSize();
}

#include <kgenericfactory.h>
typedef KGenericFactory<InputWindowPlugin> InputWindowPluginFactory;
K_EXPORT_COMPONENT_FACTORY( skimplugin_inputwindow,
                              InputWindowPluginFactory( "skimplugin_inputwindow" ) )
                              
InputWindowPlugin::InputWindowPlugin( QObject *parent, const char *name, const QStringList & /*args*/ )
 : SkimPlugin(InputWindowPluginFactory::instance(), parent, name)
{
    inputw = new inputWindow(static_cast<SkimPluginManager *>(parent), 0,0, TOP_LEVEL_WFLAGS);
    connect( this, SIGNAL(settingsChanged()), inputw, SLOT(changeSetting()));
}

void InputWindowPlugin::toggleStick() {
    inputw->toggleStick();
}

InputWindowPlugin::~InputWindowPlugin()
{
    delete inputw;
}

#include "inputwindow.moc"
