/* poppler-form.h: qt4 interface to poppler
 * Copyright (C) 2007-2008, 2011, Pino Toscano <pino@kde.org>
 * Copyright (C) 2008, 2011, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.org>
 *
 * 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, 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.
 */

#include "poppler-qt4.h"

#include <QtCore/QSizeF>

#include <Form.h>
#include <Object.h>
#include <Link.h>

#include "poppler-form.h"
#include "poppler-page-private.h"
#include "poppler-private.h"
#include "poppler-annotation-helper.h"

#include <math.h>

namespace {

Qt::Alignment formTextAlignment(Object *obj)
{
  Object tmp;
  int align = 0;
  if (obj->dictLookup("Q", &tmp)->isInt())
  {
    align = tmp.getInt();
  }
  tmp.free();
  Qt::Alignment qtalign;
  switch (align)
  {
    case 1:
      qtalign = Qt::AlignHCenter;
      break;
    case 2:
      qtalign = Qt::AlignRight;
      break;
    case 0:
    default:
      qtalign = Qt::AlignLeft;
  }
  return qtalign;
}

}

namespace Poppler {

FormField::FormField(FormFieldData &dd)
  : m_formData(&dd)
{
  const int rotation = m_formData->page->getRotate();
  // reading the coords
  double left, top, right, bottom;
  m_formData->fm->getRect(&left, &bottom, &right, &top);
  // build a normalized transform matrix for this page at 100% scale
  GfxState gfxState( 72.0, 72.0, m_formData->page->getCropBox(), rotation, gTrue );
  double * gfxCTM = gfxState.getCTM();
  double MTX[6];
  double pageWidth = m_formData->page->getCropWidth();
  double pageHeight = m_formData->page->getCropHeight();
  // landscape and seascape page rotation: be sure to use the correct (== rotated) page size
  if (((rotation / 90) % 2) == 1)
    qSwap(pageWidth, pageHeight);
  for ( int i = 0; i < 6; i+=2 )
  {
    MTX[i] = gfxCTM[i] / pageWidth;
    MTX[i+1] = gfxCTM[i+1] / pageHeight;
  }
  QPointF topLeft;
  XPDFReader::transform( MTX, qMin( left, right ), qMax( top, bottom ), topLeft );
  QPointF bottomRight;
  XPDFReader::transform( MTX, qMax( left, right ), qMin( top, bottom ), bottomRight );
  m_formData->box = QRectF(topLeft, QSizeF(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()));

  Dict *dict = m_formData->fm->getObj()->getDict();
  Object tmp;

  // reading the flags
  if (dict->lookup("Ff", &tmp)->isInt())
  {
    m_formData->flags = tmp.getInt();
  }
  tmp.free();
  // reading the widget annotation flags
  if (dict->lookup("F", &tmp)->isInt())
  {
    m_formData->annoflags = tmp.getInt();
  }
  tmp.free();
}

FormField::~FormField()
{
  delete m_formData;
  m_formData = 0;
}

QRectF FormField::rect() const
{
  return m_formData->box;
}

int FormField::id() const
{
  return m_formData->fm->getID();
}

QString FormField::name() const
{
  QString name;
  if (GooString *goo = m_formData->fm->getPartialName())
  {
    name = QString::fromLatin1(goo->getCString());
  }
  return name;
}

QString FormField::fullyQualifiedName() const
{
  QString name;
  if (GooString *goo = m_formData->fm->getFullyQualifiedName())
  {
    name = QString::fromLatin1(goo->getCString());
  }
  return name;
}

QString FormField::uiName() const
{
  QString name;
  if (GooString *goo = m_formData->fm->getAlternateUiName())
  {
    name = QString::fromLatin1(goo->getCString());
  }
  return name;
}

bool FormField::isReadOnly() const
{
  return m_formData->fm->isReadOnly();
}

bool FormField::isVisible() const
{
  return !(m_formData->annoflags & (1 << 1));
}

Link* FormField::activationAction() const
{
  Link* action = 0;
  if (::LinkAction *act = m_formData->fm->getActivationAction())
  {
    action = PageData::convertLinkActionToLink(act, m_formData->doc, QRectF());
  }
  return action;
}


FormFieldButton::FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w)
  : FormField(*new FormFieldData(doc, p, w))
{
}

FormFieldButton::~FormFieldButton()
{
}

FormFieldButton::FormType FormFieldButton::type() const
{
  return FormField::FormButton;
}

FormFieldButton::ButtonType FormFieldButton::buttonType() const
{
  FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm);
  switch (fwb->getButtonType())
  {
    case formButtonCheck:
      return FormFieldButton::CheckBox;
      break;
    case formButtonPush:
      return FormFieldButton::Push;
      break;
    case formButtonRadio:
      return FormFieldButton::Radio;
      break;
  }
  return FormFieldButton::CheckBox;
}

QString FormFieldButton::caption() const
{
  FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm);
  QString ret;
  if (fwb->getButtonType() == formButtonPush)
  {
    Dict *dict = m_formData->fm->getObj()->getDict();
    Object obj1;
    if (dict->lookup("MK", &obj1)->isDict())
    {
      AnnotAppearanceCharacs appearCharacs(obj1.getDict());
      if (appearCharacs.getNormalCaption())
      {
        ret = UnicodeParsedString(appearCharacs.getNormalCaption());
      }
    }
    obj1.free();
  }
  else
  {
    if (const char *goo = fwb->getOnStr())
    {
      ret = QString::fromUtf8(goo);
    }
  }
  return ret;
}

bool FormFieldButton::state() const
{
  FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm);
  return fwb->getState();
}

void FormFieldButton::setState( bool state )
{
  FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm);
  fwb->setState((GBool)state);
}

QList<int> FormFieldButton::siblings() const
{
  FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm);
  if (fwb->getButtonType() == formButtonPush)
    return QList<int>();

  QList<int> ret;
  unsigned *sibls = fwb->getSiblingsID();
  for (int i = 0; i < fwb->getNumSiblingsID(); ++i)
    ret.append(sibls[i]);

  return ret;
}


FormFieldText::FormFieldText(DocumentData *doc, ::Page *p, ::FormWidgetText *w)
  : FormField(*new FormFieldData(doc, p, w))
{
}

FormFieldText::~FormFieldText()
{
}

FormField::FormType FormFieldText::type() const
{
  return FormField::FormText;
}

FormFieldText::TextType FormFieldText::textType() const
{
  FormWidgetText* fwt = static_cast<FormWidgetText*>(m_formData->fm);
  if (fwt->isFileSelect())
    return FormFieldText::FileSelect;
  else if (fwt->isMultiline())
    return FormFieldText::Multiline;
  return FormFieldText::Normal;
}

QString FormFieldText::text() const
{
  GooString *goo = static_cast<FormWidgetText*>(m_formData->fm)->getContent();
  return UnicodeParsedString(goo);
}

void FormFieldText::setText( const QString& text )
{
  FormWidgetText* fwt = static_cast<FormWidgetText*>(m_formData->fm);
  GooString * goo = QStringToUnicodeGooString( text );
  fwt->setContent( goo );
  delete goo;
}

bool FormFieldText::isPassword() const
{
  FormWidgetText* fwt = static_cast<FormWidgetText*>(m_formData->fm);
  return fwt->isPassword();
}

bool FormFieldText::isRichText() const
{
  FormWidgetText* fwt = static_cast<FormWidgetText*>(m_formData->fm);
  return fwt->isRichText();
}

int FormFieldText::maximumLength() const
{
  FormWidgetText* fwt = static_cast<FormWidgetText*>(m_formData->fm);
  const int maxlen = fwt->getMaxLen();
  return maxlen > 0 ? maxlen : -1;
}

Qt::Alignment FormFieldText::textAlignment() const
{
  return formTextAlignment(m_formData->fm->getObj());
}

bool FormFieldText::canBeSpellChecked() const
{
  FormWidgetText* fwt = static_cast<FormWidgetText*>(m_formData->fm);
  return !fwt->noSpellCheck();
}


FormFieldChoice::FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w)
  : FormField(*new FormFieldData(doc, p, w))
{
}

FormFieldChoice::~FormFieldChoice()
{
}

FormFieldChoice::FormType FormFieldChoice::type() const
{
  return FormField::FormChoice;
}

FormFieldChoice::ChoiceType FormFieldChoice::choiceType() const
{
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  if (fwc->isCombo())
    return FormFieldChoice::ComboBox;
  return FormFieldChoice::ListBox;
}

QStringList FormFieldChoice::choices() const
{
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  QStringList ret;
  int num = fwc->getNumChoices();
  for (int i = 0; i < num; ++i)
  {
    ret.append(UnicodeParsedString(fwc->getChoice(i)));
  }
  return ret;
}

bool FormFieldChoice::isEditable() const
{
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  return fwc->isCombo() ? fwc->hasEdit() : false;
}

bool FormFieldChoice::multiSelect() const
{
//  return m_formData->flags & (1 << 21);
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  return !fwc->isCombo() ? fwc->isMultiSelect() : false;
}

QList<int> FormFieldChoice::currentChoices() const
{
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  int num = fwc->getNumChoices();
  QList<int> choices;
  for ( int i = 0; i < num; ++i )
    if ( fwc->isSelected( i ) )
      choices.append( i );
  return choices;
}

void FormFieldChoice::setCurrentChoices( const QList<int> &choice )
{
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  fwc->deselectAll();
  for ( int i = 0; i < choice.count(); ++i )
    fwc->select( choice.at( i ) );
}

Qt::Alignment FormFieldChoice::textAlignment() const
{
  return formTextAlignment(m_formData->fm->getObj());
}

bool FormFieldChoice::canBeSpellChecked() const
{
  FormWidgetChoice* fwc = static_cast<FormWidgetChoice*>(m_formData->fm);
  return !fwc->noSpellCheck();
}

}
