/////////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2015-     Statoil ASA
//  Copyright (C) 2015-     Ceetron Solutions AS
//
//  ResInsight 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.
//
//  ResInsight 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 at <http://www.gnu.org/licenses/gpl.html>
//  for more details.
//
/////////////////////////////////////////////////////////////////////////////////

#include "RicPasteEclipseCasesFeature.h"

#include "RicPasteFeatureImpl.h"

#include "RigGridManager.h"

#include "RimCaseCollection.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimMimeData.h"
#include "RimOilField.h"
#include "RimProject.h"

#include "cafPdmObjectGroup.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmReferenceHelper.h"
#include "cafSelectionManager.h"

#include <QAction>
#include <QString>

CAF_CMD_SOURCE_INIT( RicPasteEclipseCasesFeature, "RicPasteEclipseCasesFeature" );

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicPasteEclipseCasesFeature::isCommandEnabled()
{
    caf::PdmObjectGroup objectGroup;
    RicPasteFeatureImpl::findObjectsFromClipboardRefs( &objectGroup );

    std::vector<caf::PdmPointer<RimEclipseResultCase>> typedObjects;
    objectGroup.objectsByType( &typedObjects );

    if ( typedObjects.size() == 0 )
    {
        return false;
    }

    caf::PdmObjectHandle* destinationObject = dynamic_cast<caf::PdmObjectHandle*>( caf::SelectionManager::instance()->selectedItem() );

    RimIdenticalGridCaseGroup* gridCaseGroup = RicPasteFeatureImpl::findGridCaseGroup( destinationObject );
    if ( gridCaseGroup ) return true;

    return false;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicPasteEclipseCasesFeature::onActionTriggered( bool isChecked )
{
    caf::PdmObjectHandle* destinationObject = dynamic_cast<caf::PdmObjectHandle*>( caf::SelectionManager::instance()->selectedItem() );

    RimIdenticalGridCaseGroup* gridCaseGroup = RicPasteFeatureImpl::findGridCaseGroup( destinationObject );
    if ( !gridCaseGroup ) return;

    caf::PdmObjectGroup objectGroup;
    RicPasteFeatureImpl::findObjectsFromClipboardRefs( &objectGroup );

    if ( objectGroup.objects.size() == 0 ) return;

    addCasesToGridCaseGroup( objectGroup, gridCaseGroup );

    return;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicPasteEclipseCasesFeature::setupActionLook( QAction* actionToSetup )
{
    actionToSetup->setText( "Paste (Eclipse Cases)" );

    RicPasteFeatureImpl::setIconAndShortcuts( actionToSetup );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicPasteEclipseCasesFeature::addCasesToGridCaseGroup( caf::PdmObjectGroup& objectGroup, RimIdenticalGridCaseGroup* gridCaseGroup )
{
    RimProject* proj = RimProject::current();
    CVF_ASSERT( proj );

    std::vector<RimEclipseResultCase*> resultCases;

    for ( size_t i = 0; i < objectGroup.objects.size(); i++ )
    {
        RimEclipseResultCase* eclCase = dynamic_cast<RimEclipseResultCase*>( objectGroup.objects[i] );
        if ( eclCase )
        {
            RimEclipseResultCase* eclCaseCopy = new RimEclipseResultCase();
            eclCaseCopy->setCaseInfo( eclCase->caseUserDescription(), eclCase->gridFileName() );
            resultCases.push_back( eclCaseCopy );
        }
    }

    if ( resultCases.size() == 0 )
    {
        return;
    }

    RimEclipseResultCase*         mainResultCase = nullptr;
    std::vector<std::vector<int>> mainCaseGridDimensions;

    // Read out main grid and main grid dimensions if present in case group
    if ( gridCaseGroup->mainCase() )
    {
        mainResultCase = dynamic_cast<RimEclipseResultCase*>( gridCaseGroup->mainCase() );
        CVF_ASSERT( mainResultCase );

        mainResultCase->readGridDimensions( mainCaseGridDimensions );
    }

    std::vector<RimEclipseResultCase*> insertedCases;

    // Add cases to case group
    for ( size_t i = 0; i < resultCases.size(); i++ )
    {
        RimEclipseResultCase* rimResultReservoir = resultCases[i];

        proj->assignCaseIdToCase( rimResultReservoir );

        if ( gridCaseGroup->contains( rimResultReservoir ) )
        {
            continue;
        }

        insertedCases.push_back( rimResultReservoir );
    }

    // Load stuff
    for ( size_t i = 0; i < insertedCases.size(); i++ )
    {
        RimEclipseResultCase* rimResultReservoir = insertedCases[i];

        if ( !mainResultCase )
        {
            rimResultReservoir->openEclipseGridFile();
            rimResultReservoir->readGridDimensions( mainCaseGridDimensions );

            mainResultCase = rimResultReservoir;
        }
        else
        {
            std::vector<std::vector<int>> caseGridDimensions;
            rimResultReservoir->readGridDimensions( caseGridDimensions );

            bool identicalGrid = RigGridManager::isGridDimensionsEqual( mainCaseGridDimensions, caseGridDimensions );
            if ( !identicalGrid )
            {
                continue;
            }

            if ( !rimResultReservoir->openAndReadActiveCellData( mainResultCase->eclipseCaseData() ) )
            {
                CVF_ASSERT( false );
            }
        }

        RimOilField*              activeOilField = proj ? proj->activeOilField() : nullptr;
        RimEclipseCaseCollection* analysisModels = ( activeOilField ) ? activeOilField->analysisModels() : nullptr;
        if ( analysisModels ) analysisModels->insertCaseInCaseGroup( gridCaseGroup, rimResultReservoir );

        caf::PdmDocument::updateUiIconStateRecursively( rimResultReservoir );

        gridCaseGroup->updateConnectedEditors();

        for ( size_t rvIdx = 0; rvIdx < rimResultReservoir->reservoirViews.size(); rvIdx++ )
        {
            RimEclipseView* riv = rimResultReservoir->reservoirViews()[rvIdx];
            riv->loadDataAndUpdate();
        }
    }
}
