/*
 * This file is part of OpenModelica.
 *
 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
 * c/o Linköpings universitet, Department of Computer and Information Science,
 * SE-58183 Linköping, Sweden.
 *
 * All rights reserved.
 *
 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
 *
 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
 * Public License (OSMC-PL) are obtained from OSMC, either from the above
 * address, from the URLs:
 * http://www.openmodelica.org or
 * https://github.com/OpenModelica/ or
 * http://www.ida.liu.se/projects/OpenModelica,
 * and in the OpenModelica distribution.
 *
 * GNU AGPL version 3 is obtained from:
 * https://www.gnu.org/licenses/licenses.html#GPL
 *
 * This program is distributed WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
 *
 * See the full OSMC Public License conditions for more details.
 *
 */

/*
 * @author Adeel Asghar <adeel.asghar@liu.se>
 */

#include "BitmapAnnotation.h"
#include "Modeling/Commands.h"
#include "Util/ResourceCache.h"

#include <QMessageBox>

BitmapAnnotation::BitmapAnnotation(QString classFileName, QString annotation, GraphicsView *pGraphicsView)
  : ShapeAnnotation(false, pGraphicsView, 0)
{
  mpOriginItem = new OriginItem(this);
  mpOriginItem->setPassive();
  mClassFileName = classFileName;
  // set the default values
  GraphicItem::setDefaults();
  ShapeAnnotation::setDefaults();
  // set users default value by reading the settings file.
  ShapeAnnotation::setUserDefaults();
  parseShapeAnnotation(annotation);
  setShapeFlags(true);
}

BitmapAnnotation::BitmapAnnotation(ModelInstance::Bitmap *pBitmap, const QString &classFileName, bool inherited, GraphicsView *pGraphicsView)
  : ShapeAnnotation(inherited, pGraphicsView, 0)
{
  mpOriginItem = new OriginItem(this);
  mpOriginItem->setPassive();
  mpBitmap = pBitmap;
  mClassFileName = classFileName;
  // set the default values
  GraphicItem::setDefaults();
  FilledShape::setDefaults();
  ShapeAnnotation::setDefaults();
  // set users default value by reading the settings file.
  ShapeAnnotation::setUserDefaults();
  parseShapeAnnotation();
  setShapeFlags(true);
}

BitmapAnnotation::BitmapAnnotation(ModelInstance::Bitmap *pBitmap, const QString &classFileName, Element *pParent)
  : ShapeAnnotation(pParent)
{
  mpOriginItem = 0;
  mpBitmap = pBitmap;
  mClassFileName = classFileName;
  // set the default values
  GraphicItem::setDefaults();
  FilledShape::setDefaults();
  ShapeAnnotation::setDefaults();
  // set users default value by reading the settings file.
  ShapeAnnotation::setUserDefaults();
  parseShapeAnnotation();
  applyTransformation();
}

BitmapAnnotation::BitmapAnnotation(ShapeAnnotation *pShapeAnnotation, Element *pParent)
  : ShapeAnnotation(pParent)
{
  mpOriginItem = 0;
  updateShape(pShapeAnnotation);
  applyTransformation();
}

/*!
 * \brief BitmapAnnotation::BitmapAnnotation
 * Used by OMSimulator FMU ModelWidget\n
 * We always make this shape as inherited shape since its not allowed to be modified.
 * \param classFileName
 * \param pGraphicsView
 */
BitmapAnnotation::BitmapAnnotation(QString classFileName, GraphicsView *pGraphicsView)
  : ShapeAnnotation(true, pGraphicsView, 0)
{
  mpOriginItem = new OriginItem(this);
  mpOriginItem->setPassive();
  mClassFileName = classFileName;
  // set the default values
  GraphicItem::setDefaults();
  ShapeAnnotation::setDefaults();
  // set users default value by reading the settings file.
  ShapeAnnotation::setUserDefaults();
  QVector<QPointF> extents;
  extents << QPointF(-100, -100) << QPointF(100, 100);
  setExtents(extents);
  setPos(mOrigin);
  setRotation(mRotation);
  setShapeFlags(true);

  setFileName(mClassFileName);
  if (!mFileName.isEmpty() && QFile::exists(mFileName)) {
    mImage.load(mFileName);
  } else {
    mImage = ResourceCache::getImage(":/Resources/icons/bitmap-shape.svg");
  }
}

void BitmapAnnotation::parseShapeAnnotation(QString annotation)
{
  GraphicItem::parseShapeAnnotation(annotation);
  // parse the shape to get the list of attributes of Bitmap.
  QStringList list = StringHandler::getStrings(annotation);
  if (list.size() < 5) {
    return;
  }
  // 4th item is the extent points
  mExtent.parse(list.at(3));
  // 5th item is the fileName
  setFileName(StringHandler::removeFirstLastQuotes(stripDynamicSelect(list.at(4))));
  // 6th item is the imageSource
  if (list.size() >= 6) {
    mImageSource = StringHandler::removeFirstLastQuotes(stripDynamicSelect(list.at(5)));
  }
  if (!mImageSource.isEmpty()) {
    mImage.loadFromData(QByteArray::fromBase64(mImageSource.toLatin1()));
  } else if (!mFileName.isEmpty() && QFile::exists(mFileName)) {
    mImage.load(mFileName);
  } else {
    mImage = ResourceCache::getImage(":/Resources/icons/bitmap-shape.svg");
  }
}

void BitmapAnnotation::parseShapeAnnotation()
{
  GraphicsView *pGraphicsView = getContainingGraphicsView();
  GraphicItem::parseShapeAnnotation(mpBitmap, pGraphicsView);

  mExtent = mpBitmap->getExtent();
  mExtent.evaluate(pGraphicsView->getModelWidget()->getModelInstance());
  setFileName(StringHandler::removeFirstLastQuotes(stripDynamicSelect(mpBitmap->getFileName())));
  mImageSource = StringHandler::removeFirstLastQuotes(stripDynamicSelect(mpBitmap->getImageSource()));
  if (!mImageSource.isEmpty()) {
    mImage.loadFromData(QByteArray::fromBase64(mImageSource.toLatin1()));
  } else if (!mFileName.isEmpty() && QFile::exists(mFileName)) {
    mImage.load(mFileName);
  } else {
    mImage = ResourceCache::getImage(":/Resources/icons/bitmap-shape.svg");
  }
}

QRectF BitmapAnnotation::boundingRect() const
{
  return shape().boundingRect();
}

QPainterPath BitmapAnnotation::shape() const
{
  QPainterPath path;
  path.addRect(getBoundingRect());
  return path;
}

void BitmapAnnotation::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
  Q_UNUSED(option);
  Q_UNUSED(widget);
  if (mVisible) {
    drawAnnotation(painter);
  }
}

/*!
 * \brief BitmapAnnotation::drawAnnotation
 * Draws the bitmap.
 * \param painter
 */
void BitmapAnnotation::drawAnnotation(QPainter *painter)
{
  QRectF rect = getBoundingRect().normalized();
  QImage image = mImage.scaled(rect.width(), rect.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
  QPointF centerPoint = rect.center() - image.rect().center();
  QRectF target(centerPoint.x(), centerPoint.y(), image.width(), image.height());

#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
  painter->drawImage(target, mImage.flipped());
#else
  painter->drawImage(target, mImage.mirrored());
#endif
}

/*!
 * \brief BitmapAnnotation::getOMCShapeAnnotation
 * Returns Bitmap annotation in format as returned by OMC.
 * \return
 */
QString BitmapAnnotation::getOMCShapeAnnotation()
{
  QStringList annotationString;
  annotationString.append(GraphicItem::getOMCShapeAnnotation());
  // get the extents
  annotationString.append(mExtent.toQString());
  // get the file name
  annotationString.append(QString("\"").append(mOriginalFileName).append("\""));
  // get the image source
  annotationString.append(QString("\"").append(mImageSource).append("\""));
  return annotationString.join(",");
}

/*!
 * \brief BitmapAnnotation::getOMCShapeAnnotationWithShapeName
 * Returns Bitmap annotation in format as returned by OMC wrapped in Bitmap keyword.
 * \return
 */
QString BitmapAnnotation::getOMCShapeAnnotationWithShapeName()
{
  return QString("Bitmap(%1)").arg(getOMCShapeAnnotation());
}

/*!
 * \brief BitmapAnnotation::getShapeAnnotation
 * Returns Bitmap annotation.
 * \return
 */
QString BitmapAnnotation::getShapeAnnotation()
{
  QStringList annotationString;
  annotationString.append(GraphicItem::getShapeAnnotation());
  // get the extents
  if (mExtent.isDynamicSelectExpression() || mExtent.size() > 1) {
    annotationString.append(QString("extent=%1").arg(mExtent.toQString()));
  }
  // get the file name
  if (!mOriginalFileName.isEmpty()) {
    annotationString.append(QString("fileName=\"").append(mOriginalFileName).append("\""));
  }
  // get the image source
  if (!mImageSource.isEmpty()) {
    annotationString.append(QString("imageSource=\"").append(mImageSource).append("\""));
  }
  return QString("Bitmap(").append(annotationString.join(",")).append(")");
}

void BitmapAnnotation::updateShape(ShapeAnnotation *pShapeAnnotation)
{
  // set the default values
  GraphicItem::setDefaults(pShapeAnnotation);
  FilledShape::setDefaults(pShapeAnnotation);
  ShapeAnnotation::setDefaults(pShapeAnnotation);
}

ModelInstance::Extend *BitmapAnnotation::getExtend() const
{
  return mpBitmap->getParentExtend();
}
