// 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_TreeModel.hxx>

#include <inspector/MessageModel_ItemAlert.hxx>
#include <inspector/MessageModel_ItemRoot.hxx>
#include <inspector/MessageModel_ItemReport.hxx>
#include <inspector/TreeModel_ColumnType.hxx>

#include <Message.hxx>

const int COLUMN_NAME_WIDTH = 230;
const int COLUMN_SIZE_WIDTH = 30;

const int COLUMN_REAL_VALUE_WIDTH = 115;
const int COLUMN_PERCENT_VALUE_WIDTH = 50;

// =======================================================================
// function : Constructor
// purpose :
// =======================================================================
MessageModel_TreeModel::MessageModel_TreeModel (QObject* theParent)
: TreeModel_ModelBase (theParent)
{
}

// =======================================================================
// function : InitColumns
// purpose :
// =======================================================================
void MessageModel_TreeModel::InitColumns()
{
  // 0 - Name, 1 - visibility, 2 - Row
  setHeaderItem (TreeModel_ColumnType_Name,       TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH));
  setHeaderItem (TreeModel_ColumnType_Visibility, TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth()));
  setHeaderItem (TreeModel_ColumnType_Row,        TreeModel_HeaderSection ("Row", COLUMN_SIZE_WIDTH, Standard_True /*hidden*/));

  int aNextIndex = 3;
  for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++)
  {
    Message_MetricType aMetricType = (Message_MetricType)aMetricId;
    OSD_MemInfo::Counter aMemInfo;
    bool isMemInfo = Message::ToOSDMetric (aMetricType, aMemInfo);

    setHeaderItem (aNextIndex++,
      TreeModel_HeaderSection (QString("%1 [%2]").arg (Message::MetricToString (aMetricType)).arg(isMemInfo ? "Mb" : "s"),
      COLUMN_REAL_VALUE_WIDTH));
    setHeaderItem (aNextIndex++, TreeModel_HeaderSection (isMemInfo ? "Delta" : "%", COLUMN_PERCENT_VALUE_WIDTH));
  }
}

// =======================================================================
// function : GetMetricColumns
// purpose :
// =======================================================================
void MessageModel_TreeModel::GetMetricColumns (const Message_MetricType theMetricType, QList<int>& theMetricColumns)
{
  theMetricColumns.clear();
  int aNextIndex = 3; // after default parent columns, see InitColumns
  for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++)
  {
    if (theMetricType != (Message_MetricType)aMetricId)
    {
      aNextIndex += 2;
      continue;
    }
    theMetricColumns.append (aNextIndex++);
    theMetricColumns.append (aNextIndex++);
  }
}

// =======================================================================
// function : IsMetricColumn
// purpose :
// =======================================================================
bool MessageModel_TreeModel::IsMetricColumn (const int theColumnId, Message_MetricType& theMetricType, int& thePosition)
{
  int aNextIndex = 3; // after default parent columns, see InitColumns
  for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++)
  {
    if (theColumnId == aNextIndex || theColumnId == aNextIndex + 1)
    {
      theMetricType = (Message_MetricType)aMetricId;
      thePosition = theColumnId - aNextIndex;
      return true;
    }
    aNextIndex += 2;
  }
  return false;
}

// =======================================================================
// function : createRootItem
// purpose :
// =======================================================================
TreeModel_ItemBasePtr MessageModel_TreeModel::createRootItem (const int theColumnId)
{
  return MessageModel_ItemRoot::CreateItem (TreeModel_ItemBasePtr(), 0, theColumnId);
}

// =======================================================================
// function : HasReport
// purpose :
// =======================================================================
Standard_Boolean MessageModel_TreeModel::HasReport (const Handle(Message_Report)& theReport)
{
  if (columnCount() == 0)
    return Standard_False;

  MessageModel_ItemRootPtr aRootItem = itemDynamicCast<MessageModel_ItemRoot> (RootItem (0));
  return aRootItem && aRootItem->HasReport (theReport);
}

// =======================================================================
// function : AddReport
// purpose :
// =======================================================================
void MessageModel_TreeModel::AddReport (const Handle(Message_Report)& theReport,
                                        const TCollection_AsciiString& theReportDescription)
{
  for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++)
  {
    MessageModel_ItemRootPtr aRootItem = itemDynamicCast<MessageModel_ItemRoot> (RootItem (aColId));
    if (!aRootItem)
      continue;
    aRootItem->AddReport (theReport, theReportDescription);
  }

  Reset();
  EmitLayoutChanged();
}

// =======================================================================
// function : SetReport
// purpose :
// =======================================================================
void MessageModel_TreeModel::SetReport (const int theRowId, const Handle(Message_Report)& theReport,
                                        const TCollection_AsciiString& theReportDescription)
{
  for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++)
  {
    MessageModel_ItemRootPtr aRootItem = itemDynamicCast<MessageModel_ItemRoot> (RootItem (aColId));
    if (!aRootItem)
      continue;
    aRootItem->SetReport (theRowId, theReport, theReportDescription);
  }
  Reset();
  EmitLayoutChanged();
}

// =======================================================================
// function : Reports
// purpose :
// =======================================================================
const NCollection_List<MessageModel_ReportInformation>& MessageModel_TreeModel::Reports() const
{
  MessageModel_ItemRootPtr aRootItem = itemDynamicCast<MessageModel_ItemRoot> (RootItem (0));
  return aRootItem->Reports();
}

// =======================================================================
// function : UpdateTreeModel
// purpose :
// =======================================================================
void MessageModel_TreeModel::SetRootItemName (const TCollection_AsciiString& theName)
{
  MessageModel_ItemRootPtr aRootItem = itemDynamicCast<MessageModel_ItemRoot> (RootItem (0));
  if (aRootItem)
    aRootItem->SetName (theName);
}

// =======================================================================
// function : UpdateTreeModel
// purpose :
// =======================================================================
void MessageModel_TreeModel::UpdateTreeModel()
{
  Reset();
  EmitLayoutChanged();
}