// Created on: 2021-04-27
// Created by: Natalia ERMOLAEVA
// Copyright (c) 2021 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <inspector/MessageModel_Actions.hxx>

#include <inspector/MessageModel_ItemReport.hxx>
#include <inspector/MessageModel_ItemRoot.hxx>
#include <inspector/MessageModel_ItemAlert.hxx>
#include <inspector/MessageModel_TreeModel.hxx>
#include <inspector/TInspectorAPI_PluginParameters.hxx>
#include <inspector/ViewControl_Tools.hxx>

#include <BRepBuilderAPI_MakeEdge.hxx>
#include <Message.hxx>
#include <Message_AlertExtended.hxx>
#include <Message_Messenger.hxx>
#include <Message_PrinterToReport.hxx>
#include <OSD_Chronometer.hxx>
#include <Quantity_Color.hxx>
#include <Quantity_ColorRGBA.hxx>
#include <TCollection_AsciiString.hxx>
#include <TopoDS_AlertAttribute.hxx>

#include <Standard_WarningsDisable.hxx>
#include <QAction>
#include <QFileDialog>
#include <QItemSelectionModel>
#include <QMenu>
#include <QMessageBox>
#include <QWidget>
#include <Standard_WarningsRestore.hxx>

// =======================================================================
// function : Constructor
// purpose :
// =======================================================================
MessageModel_Actions::MessageModel_Actions(QWidget*                theParent,
                                           MessageModel_TreeModel* theTreeModel,
                                           QItemSelectionModel*    theModel)
    : QObject(theParent),
      myTreeModel(theTreeModel),
      mySelectionModel(theModel)
{
  myActions.insert(
    MessageModel_ActionType_Activate,
    ViewControl_Tools::CreateAction(tr("Activate"), SLOT(OnActivateReport()), parent(), this));
  myActions.insert(
    MessageModel_ActionType_Deactivate,
    ViewControl_Tools::CreateAction(tr("Deactivate"), SLOT(OnDeactivateReport()), parent(), this));
  myActions.insert(
    MessageModel_ActionType_Clear,
    ViewControl_Tools::CreateAction(tr("Clear"), SLOT(OnClearReport()), parent(), this));
  myActions.insert(MessageModel_ActionType_ExportToShapeView,
                   ViewControl_Tools::CreateAction(tr("Export to ShapeView"),
                                                   SLOT(OnExportToShapeView()),
                                                   parent(),
                                                   this));
}

// =======================================================================
// function : GetAction
// purpose :
// =======================================================================
QAction* MessageModel_Actions::GetAction(const MessageModel_ActionType& theType)
{
  return myActions.contains(theType) ? myActions[theType] : 0;
}

// =======================================================================
// function : AddMenuActions
// purpose :
// =======================================================================
void MessageModel_Actions::AddMenuActions(const QModelIndexList& theSelectedIndices, QMenu* theMenu)
{
  MessageModel_ItemRootPtr   aRootItem;
  MessageModel_ItemReportPtr aReportItem;
  MessageModel_ItemAlertPtr  anAlertItem;
  for (QModelIndexList::const_iterator aSelIt = theSelectedIndices.begin();
       aSelIt != theSelectedIndices.end();
       aSelIt++)
  {
    QModelIndex anIndex = *aSelIt;
    if (anIndex.column() != 0)
      continue;

    TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex(anIndex);
    if (!anItemBase)
      continue;

    aRootItem = itemDynamicCast<MessageModel_ItemRoot>(anItemBase);
    if (aRootItem)
      break;

    aReportItem = itemDynamicCast<MessageModel_ItemReport>(anItemBase);
    if (aReportItem)
      break;

    anAlertItem = itemDynamicCast<MessageModel_ItemAlert>(anItemBase);
    if (anAlertItem)
      break;
  }

  if (aReportItem && !aReportItem->GetReport().IsNull())
  {
    theMenu->addAction(myActions[MessageModel_ActionType_Deactivate]);
    theMenu->addAction(myActions[MessageModel_ActionType_Activate]);
    theMenu->addAction(myActions[MessageModel_ActionType_Clear]);
  }
  else if (anAlertItem)
  {
    theMenu->addAction(myActions[MessageModel_ActionType_ExportToShapeView]);
  }

  theMenu->addSeparator();
}

// =======================================================================
// function : getSelectedReport
// purpose :
// =======================================================================
Handle(Message_Report) MessageModel_Actions::getSelectedReport(QModelIndex& theReportIndex) const
{
  MessageModel_ItemReportPtr aReportItem;
  QModelIndexList            aSelectedIndices = mySelectionModel->selectedIndexes();
  for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin();
       aSelIt != aSelectedIndices.end();
       aSelIt++)
  {
    QModelIndex anIndex = *aSelIt;
    if (anIndex.column() != 0)
      continue;

    TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex(anIndex);
    if (!anItemBase)
      continue;

    aReportItem    = itemDynamicCast<MessageModel_ItemReport>(anItemBase);
    theReportIndex = anIndex;
    if (aReportItem)
      break;
  }
  if (!aReportItem)
    return NULL;

  return aReportItem->GetReport();
}

// =======================================================================
// function : OnActivateReport
// purpose :
// =======================================================================
static Handle(Message_PrinterToReport) MyPrinterToReport;
static Message_SequenceOfPrinters      MyDeactivatedPrinters;

void MessageModel_Actions::OnActivateReport()
{
  if (MyPrinterToReport.IsNull())
    MyPrinterToReport = new Message_PrinterToReport();

  if (MyPrinterToReport->Report()->IsActiveInMessenger())
    return;

  MyDeactivatedPrinters = Message::DefaultMessenger()->Printers();
  Message::DefaultMessenger()->ChangePrinters().Clear();

  Message::DefaultMessenger()->AddPrinter(MyPrinterToReport);
  Message::DefaultReport()->UpdateActiveInMessenger();

  myTreeModel->UpdateTreeModel();
}

// =======================================================================
// function : OnDeactivateReport
// purpose :
// =======================================================================
void MessageModel_Actions::OnDeactivateReport()
{
  if (MyPrinterToReport.IsNull() || !MyPrinterToReport->Report()->IsActiveInMessenger())
    return;

  Message::DefaultMessenger()->RemovePrinter(MyPrinterToReport);
  Message::DefaultMessenger()->ChangePrinters().Assign(MyDeactivatedPrinters);

  myTreeModel->UpdateTreeModel();
}

// =======================================================================
// function : OnClearReport
// purpose :
// =======================================================================
void MessageModel_Actions::OnClearReport()
{
  QModelIndex            aReportIndex;
  Handle(Message_Report) aReport = getSelectedReport(aReportIndex);
  if (aReport.IsNull())
    return;

  aReport->Clear();
  myTreeModel->UpdateTreeModel();
}

// =======================================================================
// function : OnExportToShapeView
// purpose :
// =======================================================================
void MessageModel_Actions::OnExportToShapeView()
{
  TCollection_AsciiString aPluginName("TKShapeView");

  NCollection_List<Handle(Standard_Transient)> aPluginParameters;
  if (myParameters->FindParameters(aPluginName))
    aPluginParameters = myParameters->Parameters(aPluginName);
  NCollection_List<TCollection_AsciiString> anItemNames;
  if (myParameters->FindSelectedNames(aPluginName))
    anItemNames = myParameters->GetSelectedNames(aPluginName);

  QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes();
  QStringList     anExportedPointers;
  for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin();
       aSelIt != aSelectedIndices.end();
       aSelIt++)
  {
    QModelIndex anIndex = *aSelIt;
    if (anIndex.column() != 0)
      continue;

    TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex(anIndex);
    if (!anItemBase)
      continue;

    MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast<MessageModel_ItemAlert>(anItemBase);
    if (!anAlertItem)
      continue;

    Handle(Message_Alert) anAlert = anAlertItem->GetAlert();
    if (anAlert.IsNull())
      continue;

    Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast(anAlert);
    if (anExtAlert.IsNull())
      continue;

    Handle(Message_Attribute) anAttribute = anExtAlert->Attribute();
    if (anAttribute.IsNull())
      continue;

    if (!anAttribute->IsKind(STANDARD_TYPE(TopoDS_AlertAttribute)))
      continue;

    const TopoDS_Shape aShape = Handle(TopoDS_AlertAttribute)::DownCast(anAttribute)->GetShape();
    if (aShape.IsNull())
      continue;
    aPluginParameters.Append(aShape.TShape());
    anItemNames.Append(TInspectorAPI_PluginParameters::ParametersToString(aShape));

    anExportedPointers.append(Standard_Dump::GetPointerInfo(aShape.TShape(), true).ToCString());
  }

  if (anExportedPointers.empty())
    return;
  myParameters->SetSelectedNames(aPluginName, anItemNames);
  myParameters->SetParameters(aPluginName, aPluginParameters);
  QMessageBox::information(0,
                           "Information",
                           QString("TShapes '%1' are sent to %2 tool.")
                             .arg(anExportedPointers.join(", "))
                             .arg(QString(aPluginName.ToCString())));
}