/*
 * This file is part of OpenModelica.
 *
 * Copyright (c) 1998-2010, Linköpings University,
 * Department of Computer and Information Science,
 * SE-58183 Linköping, Sweden.
 *
 * All rights reserved.
 *
 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THIS OSMC PUBLIC
 * LICENSE (OSMC-PL). ANY USE, REPRODUCTION OR DISTRIBUTION OF
 * THIS PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THE OSMC
 * PUBLIC LICENSE.
 *
 * The OpenModelica software and the Open Source Modelica
 * Consortium (OSMC) Public License (OSMC-PL) are obtained
 * from Linköpings University, either from the above address,
 * from the URL: http://www.ida.liu.se/projects/OpenModelica
 * and in the OpenModelica distribution.
 *
 * 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.
 *
 * For more information about the Qt-library visit TrollTech's webpage
 * regarding the Qt licence: http://www.trolltech.com/products/qt/licensing.html
 */

/*!
* \file singleApplication.cpp
* \author
* \date 2011
*/

#include "VisualizeApplication.h"
#include "VisualizeWindow.h"
#include <QTimer>

using namespace OMVisualize;

/*! \brief This class is used to create the single application to work.*/
VisualizeApplication::VisualizeApplication(int &argc, char *argv[], const QString uniqueKey)
  : QApplication(argc, argv)
{
  mSharedMemory.setKey(uniqueKey);
  if (mSharedMemory.attach())
    mIsRunning = true;
  else
  {
    mIsRunning = false;
    // attach data to shared memory.
    QByteArray byteArray("0"); // default value to note that no message is available.
    if (!mSharedMemory.create(4096))
    {
      printf("Unable to create shared memory for OMVisualize.");
      return;
    }
    mSharedMemory.lock();
    char *to = (char*)mSharedMemory.data();
    const char *from = byteArray.data();
    memcpy(to, from, qMin(mSharedMemory.size(), byteArray.size()));
    mSharedMemory.unlock();
    // start checking for messages of other instances.
    mpTimer = new QTimer(this);
    connect(mpTimer, SIGNAL(timeout()), SLOT(checkForMessage()));
    mpTimer->start(100);        // after every 0.1 second we check the shared memory
  }
}

bool VisualizeApplication::isRunning()
{
  return mIsRunning;
}

void VisualizeApplication::sendMessage(QStringList arguments)
{
  QByteArray byteArray("1");
  byteArray.append(arguments.join(";").toUtf8());
  byteArray.append('\0'); // < should be as char here, not a string!
  mSharedMemory.lock();
  char *to = (char*)mSharedMemory.data();
  const char *from = byteArray.data();
  memcpy(to, from, qMin(mSharedMemory.size(), byteArray.size()));
  mSharedMemory.unlock();
}

void VisualizeApplication::launchNewApplication(QStringList arguments)
{
  QByteArray byteArray("2");
  byteArray.append(arguments.join(";").toUtf8());
  byteArray.append('\0'); // < should be as char here, not a string!
  mSharedMemory.lock();
  char *to = (char*)mSharedMemory.data();
  const char *from = byteArray.data();
  memcpy(to, from, qMin(mSharedMemory.size(), byteArray.size()));
  mSharedMemory.unlock();
}

bool VisualizeApplication::notify(QObject *receiver, QEvent *event)
{
  try
  {
    return QApplication::notify(receiver, event);
  }
  catch (VisualizeException &e)
  {
    QMessageBox *msgBox = new QMessageBox();
    msgBox->setWindowTitle(QString("OMVisualize - Error"));
    msgBox->setIcon(QMessageBox::Warning);
    msgBox->setText(QString(e.what()));
    msgBox->setStandardButtons(QMessageBox::Ok);
    msgBox->setDefaultButton(QMessageBox::Ok);
    msgBox->exec();
    return true;
  }
}

void VisualizeApplication::checkForMessage()
{
  mSharedMemory.lock();
  QByteArray byteArray = QByteArray((char*)mSharedMemory.constData(), mSharedMemory.size());
  mSharedMemory.unlock();
  if (byteArray.left(1) == "0")
    return;
  char type = byteArray.at(0);
  byteArray.remove(0, 1);        // remove the one we put at the start of the bytearray while writing to memory
  QStringList arguments = QString::fromUtf8(byteArray.constData()).split(";");
  // remove message from shared memory.
  byteArray = "0";
  mSharedMemory.lock();
  char *to = (char*)mSharedMemory.data();
  const char *from = byteArray.data();
  memcpy(to, from, qMin(mSharedMemory.size(), byteArray.size()));
  mSharedMemory.unlock();
  // if type is 1 send message to current tab
  // if type is 2 launch a new tab
  if (type == '2')
    emit newApplicationLaunched(arguments);
  else
    emit messageAvailable(arguments);
}
