/**********************************************************************************************
    Copyright (C) 2014 Oliver Eichler <oliver.eichler@gmx.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 3 of the License, 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, see <http://www.gnu.org/licenses/>.

**********************************************************************************************/

#include "gis/db/CDBItem.h"

#include <QRegularExpression>
#include <QtSql>

#include "gis/CGisWorkspace.h"
#include "gis/db/IDBFolder.h"
#include "gis/db/macros.h"

namespace {
/**
   @brief Cut a stored item comment down to tool tip size

   The comment is the item's info as HTML. Cutting it on character level can end inside a tag and
   QTextDocument will swallow everything behind an unterminated one, leaving an empty tool tip and an
   empty status line in the delegate. Embedded images are the worst case: a base64 data URI eats the
   whole budget on its own. Drop images first - the tool tip is a text summary - then cut back to the
   last complete tag.

   @param comment  The comment as read from the database
   @return The comment ready to be used as tool tip
 */
QString shortenComment(QString comment) {
  static const QRegularExpression reImage("<img[^>]*>", QRegularExpression::CaseInsensitiveOption);
  comment.remove(reImage);

  if (comment.size() > 300) {
    comment.truncate(297);
    const qsizetype idxOpen = comment.lastIndexOf('<');
    if (idxOpen > comment.lastIndexOf('>')) {
      comment.truncate(idxOpen);
    }
    comment += "...";
  }

  return comment;
}
}  // namespace

CDBItem::CDBItem(QSqlDatabase& db, quint64 id, IDBFolder* parent) : IDBItem(parent, eTypeItem), db(db), id(id) {
  QSqlQuery query(db);
  query.prepare("SELECT type, keyqms, icon, name, date, comment FROM items WHERE id=:id");
  query.bindValue(":id", id);
  QUERY_EXEC(return);
  if (query.next()) {
    type = query.value(0).toInt();
    key = query.value(1).toString();
    displayIcon.loadFromData(query.value(2).toByteArray(), "PNG");
    setName(query.value(3).toString());

    date = query.value(4).toDateTime();

    setToolTip(shortenComment(query.value(5).toString()));
  }

  updateAge();
}

void CDBItem::updateAge() {
  QSqlQuery query(db);
  query.prepare("SELECT trash FROM items WHERE id=:id");
  query.bindValue(":id", id);
  QUERY_EXEC(return);
  if (!query.next()) {
    return;
  }

  if ((parent() != nullptr) && (parent()->type() == IDBFolder::eTypeLostFound)) {
    QString date = query.value(0).toString();
    QDateTime timestamp;

    // The time format can differ by database type
    if (date.contains('T')) {
      timestamp = QDateTime::fromString(date, "yyyy-MM-ddThh:mm:ss");
    } else {
      timestamp = QDateTime::fromString(date, "yyyy-MM-dd hh:mm:ss");
    }

    if (timestamp.isValid()) {
      setAge(timestamp);
    }
  }
}

void CDBItem::toggle() {
  IDBFolder* folder = dynamic_cast<IDBFolder*>(parent());
  if (nullptr == folder) {
    return;
  }

  if (getCheckState() == Qt::Checked) {
    // make sure the project is shown on the workspace
    CEvtD2WShowFolder* evt1 = new CEvtD2WShowFolder(folder->getId(), folder->getDBName());
    CGisWorkspace::self().postEventForWks(evt1);

    // tell the project to load the item from the database
    CEvtD2WShowItems* evt2 = new CEvtD2WShowItems(folder->getId(), folder->getDBName());
    evt2->items << evt_item_t(id, type);
    CGisWorkspace::self().postEventForWks(evt2);
  } else {
    // tell the project to remove the item
    CEvtD2WHideItems* evt2 = new CEvtD2WHideItems(folder->getId(), folder->getDBName());
    evt2->keys << key;
    CGisWorkspace::self().postEventForWks(evt2);
  }
}

void CDBItem::remove() {
  IDBFolder* folder = dynamic_cast<IDBFolder*>(parent());
  if (nullptr == folder) {
    return;
  }

  if (getCheckState() == Qt::Checked) {
    CEvtD2WHideItems* evt = new CEvtD2WHideItems(folder->getId(), folder->getDBName());
    evt->keys << key;
    CGisWorkspace::self().postEventForWks(evt);
  }

  QSqlQuery query(db);
  query.prepare("DELETE FROM folder2item WHERE parent=:parent AND child=:child");
  query.bindValue(":parent", folder->getId());
  query.bindValue(":child", id);
  QUERY_EXEC();

  folder->updateChildStatistics();
}
