/////////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2017 Statoil ASA
//
//  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 "RiuSummaryVectorSelectionUi.h"

#include "RiaCurveSetDefinition.h"
#include "RiaOptionItemFactory.h"
#include "RiaStdStringTools.h"
#include "RiaSummaryCurveDefinition.h"
#include "RiaSummaryDefines.h"

#include "RifEclipseSummaryAddress.h"
#include "RifReaderEclipseSummary.h"
#include "RifSummaryReaderInterface.h"

#include "RimObservedDataCollection.h"
#include "RimObservedSummaryData.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCalculation.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCaseMainCollection.h"

#include "RiuSummaryCurveDefinitionKeywords.h"
#include "RiuSummaryQuantityNameInfoProvider.h"

#include "cafPdmPointer.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiTreeSelectionEditor.h"

#include <QDebug>

#include <algorithm>

CAF_PDM_SOURCE_INIT( RiuSummaryVectorSelectionUi, "RicSummaryAddressSelection" );

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class SummaryIdentifierAndField
{
public:
    SummaryIdentifierAndField()
        : m_summaryIdentifier( (RifEclipseSummaryAddress::SummaryIdentifierType)0 )
        , m_pdmField( nullptr )
    {
    }

    SummaryIdentifierAndField( const SummaryIdentifierAndField& ) = delete;

    SummaryIdentifierAndField( RifEclipseSummaryAddress::SummaryIdentifierType summaryIdentifier )
        : m_summaryIdentifier( summaryIdentifier )
        , m_pdmField( new caf::PdmField<std::vector<QString>>() )
    {
    }

    virtual ~SummaryIdentifierAndField();

    RifEclipseSummaryAddress::SummaryIdentifierType summaryIdentifier() const { return m_summaryIdentifier; }
    caf::PdmField<std::vector<QString>>*            pdmField() { return m_pdmField; }

private:
    RifEclipseSummaryAddress::SummaryIdentifierType m_summaryIdentifier;
    caf::PdmField<std::vector<QString>>*            m_pdmField;
};

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SummaryIdentifierAndField::~SummaryIdentifierAndField()
{
    delete m_pdmField;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuSummaryVectorSelectionUi::RiuSummaryVectorSelectionUi()
    : m_identifierFieldsMap( {
          { RifEclipseSummaryAddress::SUMMARY_FIELD,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_AQUIFER,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_AQUIFER_NUMBER ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_NETWORK,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_MISC,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_REGION,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_REGION_NUMBER ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_REGION_2_REGION ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_GROUP,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_GROUP_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_WELL,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_LGR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_WELL_LGR,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_LGR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_SEGMENT_NUMBER ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_BLOCK,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_LGR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },
          { RifEclipseSummaryAddress::SUMMARY_IMPORTED,
            { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ),
              new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_ID ) } },

      } )
    , m_showIndividualEnsembleCases( true )
{
    CAF_PDM_InitFieldNoDefault( &m_selectedSources, "SummaryCases", "Cases" );
    m_selectedSources.uiCapability()->setAutoAddingOptionFromValue( false );

    CAF_PDM_InitFieldNoDefault( &m_currentSummaryCategory, "CurrentSummaryCategory", "Current Summary Category" );
    CAF_PDM_InitFieldNoDefault( &m_selectedSummaryCategories, "SelectedSummaryCategories", "Summary Categories" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_FIELD][0]->pdmField(), "FieldVectors", "Field vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_FIELD][1]->pdmField(),
                                "FieldCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][0]->pdmField(), "Aquifers", "Aquifers" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][1]->pdmField(),
                                "AquiferVectors",
                                "Aquifer Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][2]->pdmField(),
                                "AquifierCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_NETWORK][0]->pdmField(),
                                "NetworkVectors",
                                "Network Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_NETWORK][1]->pdmField(),
                                "NetworkCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_MISC][0]->pdmField(), "MiscVectors", "Misc Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_MISC][1]->pdmField(),
                                "MiscCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][0]->pdmField(), "Regions", "Regions" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][1]->pdmField(),
                                "RegionsVectors",
                                "Regions Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][2]->pdmField(),
                                "RegionCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][0]->pdmField(),
                                "Region2RegionRegions",
                                "Regions" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][1]->pdmField(),
                                "Region2RegionVectors",
                                "Region2s Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][2]->pdmField(),
                                "Region2RegionCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_GROUP][0]->pdmField(),
                                "WellGroupWellGroupNames",
                                "Groups" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_GROUP][1]->pdmField(),
                                "WellGroupVectors",
                                "Well Group Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_GROUP][2]->pdmField(),
                                "WellGroupCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][0]->pdmField(), "WellWellName", "Wells" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][1]->pdmField(), "WellVectors", "Well Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][2]->pdmField(),
                                "WellCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][0]->pdmField(),
                                "WellCompletionWellName",
                                "Wells" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][1]->pdmField(),
                                "WellCompletionIjk",
                                "Cell IJK" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][2]->pdmField(),
                                "WellCompletionVectors",
                                "Well Completion Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][3]->pdmField(),
                                "WellCompletionCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][0]->pdmField(),
                                "WellCompletionLgrLgrName",
                                "LGR Names" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][1]->pdmField(),
                                "WellCompletionLgrWellName",
                                "Wells" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][2]->pdmField(),
                                "WellCompletionLgrIjk",
                                "Cell IJK" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][3]->pdmField(),
                                "WellCompletionLgrVectors",
                                "Well Completion Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][4]->pdmField(),
                                "WellCompletionLgrCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][0]->pdmField(), "WellLgrLgrName", "LGR Names" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][1]->pdmField(), "WellLgrWellName", "Wells" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][2]->pdmField(), "WellLgrVectors", "Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][3]->pdmField(),
                                "WellLgrCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][0]->pdmField(),
                                "WellSegmentWellName",
                                "Wells" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][1]->pdmField(),
                                "WellSegmentNumber",
                                "Segments" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][2]->pdmField(),
                                "WellSegmentVectors",
                                "Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][3]->pdmField(),
                                "WellSegmentCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][0]->pdmField(), "BlockIjk", "Cell IJK" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][1]->pdmField(), "BlockVectors", "Block Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][2]->pdmField(),
                                "BlockCalculationIds",
                                "Calculation Ids" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][0]->pdmField(),
                                "BlockLgrLgrName",
                                "LGR Names" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][1]->pdmField(), "BlockLgrIjk", "Cell IJK" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][2]->pdmField(),
                                "BlockLgrVectors",
                                "Block Vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][3]->pdmField(),
                                "BlockLgrCalculationIds",
                                "CalculationIds" );

    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_IMPORTED][0]->pdmField(),
                                "ImportedVectors",
                                "Imported vectors" );
    CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_IMPORTED][1]->pdmField(),
                                "ImportedCalculationIds",
                                "Calculation Ids" );

    for ( const auto& itemTypes : m_identifierFieldsMap )
    {
        for ( const auto& itemInputType : itemTypes.second )
        {
            itemInputType->pdmField()->uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );

            itemInputType->pdmField()->uiCapability()->setUiLabelPosition( itemTypes.second.size() > 2 ? caf::PdmUiItemInfo::TOP
                                                                                                       : caf::PdmUiItemInfo::HIDDEN );

            itemInputType->pdmField()->uiCapability()->setAutoAddingOptionFromValue( false );
        }
        itemTypes.second.back()->pdmField()->uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
    }

    m_selectedSources.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
    m_selectedSources.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
    m_selectedSources.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );

    m_selectedSummaryCategories.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
    m_selectedSummaryCategories.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );

    m_currentSummaryCategory.uiCapability()->setUiHidden( true );
    m_multiSelectionMode = false;
    m_hideEnsembles      = false;
    m_hideSummaryCases   = false;

    m_hideDifferenceVectors                 = false;
    m_hideHistoryVectors                    = false;
    m_hideVectorsWithoutHistory             = false;
    m_hideCalculationIncompatibleCategories = false;

    m_prevCurveCount    = 0;
    m_prevCurveSetCount = 0;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuSummaryVectorSelectionUi::~RiuSummaryVectorSelectionUi()
{
    for ( const auto& identifierAndFieldList : m_identifierFieldsMap )
    {
        for ( const auto& identifierAndField : identifierAndFieldList.second )
        {
            delete identifierAndField;
        }
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaSummaryCurveDefinition> RiuSummaryVectorSelectionUi::allCurveDefinitionsFromSelection() const
{
    std::vector<RiaSummaryCurveDefinition> curveDefVector;

    {
        std::set<RiaSummaryCurveDefinition> curveDefinitions;
        std::set<RifEclipseSummaryAddress>  selectedAddressesFromUi = buildAddressListFromSelections();

        for ( SummarySource* currSource : selectedSummarySources() )
        {
            RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>( currSource );
            if ( sumCase == nullptr ) continue;

            std::set<RifEclipseSummaryAddress> addressesFromSource;
            std::vector<RimSummaryCase*>       casesFromSource;

            RifSummaryReaderInterface* reader = sumCase ? sumCase->summaryReader() : nullptr;
            if ( reader )
            {
                addressesFromSource.insert( reader->allResultAddresses().begin(), reader->allResultAddresses().end() );
                casesFromSource.push_back( sumCase );
            }

            for ( auto caseFromSource : casesFromSource )
            {
                for ( const auto& addressFromSource : addressesFromSource )
                {
                    if ( selectedAddressesFromUi.count( addressFromSource ) > 0 )
                    {
                        curveDefinitions.insert( RiaSummaryCurveDefinition( caseFromSource, addressFromSource, false ) );
                    }
                }
            }
        }

        std::copy( curveDefinitions.begin(), curveDefinitions.end(), std::back_inserter( curveDefVector ) );
    }

    return curveDefVector;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaCurveSetDefinition> RiuSummaryVectorSelectionUi::allCurveSetDefinitionsFromSelections() const
{
    std::vector<RiaCurveSetDefinition> curveSetDefVector;
    std::set<RiaCurveSetDefinition>    curveSetDefinitions;
    std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections();

    for ( SummarySource* currSource : selectedSummarySources() )
    {
        RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( currSource );
        if ( !ensemble ) continue;

        std::set<RifEclipseSummaryAddress> addressesFromSource;

        // Build case list
        auto addresses = ensemble->ensembleSummaryAddresses();
        addressesFromSource.insert( addresses.begin(), addresses.end() );

        for ( const auto& addressFromSource : addressesFromSource )
        {
            if ( selectedAddressesFromUi.count( addressFromSource ) > 0 )
            {
                curveSetDefinitions.insert( RiaCurveSetDefinition( ensemble, addressFromSource ) );
            }
        }
    }

    std::copy( curveSetDefinitions.begin(), curveSetDefinitions.end(), std::back_inserter( curveSetDefVector ) );
    return curveSetDefVector;
}

//--------------------------------------------------------------------------------------------------
/// One CurveDefinition pr ensemble curve set,
/// but if enableIndividualEnsembleCaseSelection has been enabled,
/// the ensembles are never available for direct selection, and this method will always return the
/// "expanded" set of curvedefinitions
//--------------------------------------------------------------------------------------------------
std::vector<RiaSummaryCurveDefinition> RiuSummaryVectorSelectionUi::selection() const
{
    std::vector<RiaSummaryCurveDefinition> curveDefSelection;
    std::set<RifEclipseSummaryAddress>     selectedAddressesFromUi = buildAddressListFromSelections();
    for ( SummarySource* currSource : selectedSummarySources() )
    {
        RimSummaryCaseCollection* ensemble   = dynamic_cast<RimSummaryCaseCollection*>( currSource );
        RimSummaryCase*           sourceCase = dynamic_cast<RimSummaryCase*>( currSource );

        if ( ensemble )
        {
            std::set<RifEclipseSummaryAddress> addressUnion = ensemble->ensembleSummaryAddresses();
            for ( const auto& addr : selectedAddressesFromUi )
            {
                if ( addressUnion.count( addr ) )
                {
                    curveDefSelection.push_back( RiaSummaryCurveDefinition( ensemble, addr ) );
                }
            }
        }
        else
        {
            if ( !( sourceCase && sourceCase->summaryReader() ) ) continue;

            const std::set<RifEclipseSummaryAddress>& readerAddresses = sourceCase->summaryReader()->allResultAddresses();
            for ( const auto& addr : selectedAddressesFromUi )
            {
                if ( readerAddresses.count( addr ) )
                {
                    curveDefSelection.push_back( RiaSummaryCurveDefinition( sourceCase, addr, false ) );
                }
            }
        }
    }

    return curveDefSelection;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setMultiSelectionMode( bool multiSelectionMode )
{
    m_multiSelectionMode = multiSelectionMode;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideEnsembles( bool hide )
{
    m_hideEnsembles = hide;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideSummaryCases( bool hide )
{
    m_hideSummaryCases = hide;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::enableIndividualEnsembleCaseSelection( bool enable )
{
    m_showIndividualEnsembleCases = enable;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideDifferenceVectors( bool hide )
{
    m_hideDifferenceVectors = hide;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideHistoryVectors( bool hide )
{
    m_hideHistoryVectors = hide;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideVectorsWithoutHistory( bool hide )
{
    m_hideVectorsWithoutHistory = hide;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideCalculationIncompatibleCategories( bool hide )
{
    m_hideCalculationIncompatibleCategories = hide;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setFieldChangedHandler( const std::function<void()>& handlerFunc )
{
    m_toggleChangedHandler = handlerFunc;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setDefaultSelection( const std::vector<SummarySource*>& defaultSources )
{
    RimProject* proj        = RimProject::current();
    auto        allSumCases = proj->allSummaryCases();

    if ( allSumCases.size() > 0 )
    {
        RifEclipseSummaryAddress defaultAddress;

        std::vector<SummarySource*> selectTheseSources = defaultSources;
        if ( selectTheseSources.empty() ) selectTheseSources.push_back( allSumCases[0] );

        std::vector<RiaSummaryCurveDefinition> curveDefs;
        for ( SummarySource* s : selectTheseSources )
        {
            RimSummaryCase*           sumCase  = dynamic_cast<RimSummaryCase*>( s );
            RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( s );
            if ( ensemble )
            {
                curveDefs.push_back( RiaSummaryCurveDefinition( ensemble, defaultAddress ) );
            }
            else
            {
                curveDefs.push_back( RiaSummaryCurveDefinition( sumCase, defaultAddress, false ) );
            }
        }

        setSelectedCurveDefinitions( curveDefs );
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
    RiuSummaryVectorSelectionUi::optionsForSummaryDataSource( bool hideSummaryCases, bool hideEnsembles, bool showIndividualEnsembleCases )
{
    QList<caf::PdmOptionItemInfo> options;

    RimProject*               proj = RimProject::current();
    std::vector<RimOilField*> oilFields;

    proj->allOilFields( oilFields );
    for ( RimOilField* oilField : oilFields )
    {
        RimSummaryCaseMainCollection* sumCaseMainColl = oilField->summaryCaseMainCollection();
        if ( sumCaseMainColl )
        {
            if ( !hideSummaryCases )
            {
                // Top level cases
                for ( const auto& sumCase : sumCaseMainColl->topLevelSummaryCases() )
                {
                    options.push_back( caf::PdmOptionItemInfo( sumCase->displayCaseName(), sumCase ) );
                }
            }

            // Ensembles
            if ( !hideEnsembles )
            {
                bool ensembleHeaderCreated = false;
                for ( const auto& sumCaseColl : sumCaseMainColl->summaryCaseCollections() )
                {
                    if ( !sumCaseColl->isEnsemble() ) continue;

                    if ( !ensembleHeaderCreated )
                    {
                        options.push_back( caf::PdmOptionItemInfo::createHeader( "Ensembles", true ) );
                        ensembleHeaderCreated = true;
                    }
                    // Ensemble level
                    {
                        auto optionItem = caf::PdmOptionItemInfo( sumCaseColl->name(), sumCaseColl );
                        optionItem.setLevel( 1 );
                        options.push_back( optionItem );
                    }
                }
            }

            if ( !hideSummaryCases )
            {
                // Grouped cases
                for ( const auto& sumCaseColl : sumCaseMainColl->summaryCaseCollections() )
                {
                    if ( sumCaseColl->isEnsemble() && !showIndividualEnsembleCases ) continue;

                    options.push_back( caf::PdmOptionItemInfo::createHeader( sumCaseColl->name(), true ) );

                    for ( const auto& sumCase : sumCaseColl->allSummaryCases() )
                    {
                        auto optionItem = caf::PdmOptionItemInfo( sumCase->displayCaseName(), sumCase );
                        optionItem.setLevel( 1 );
                        options.push_back( optionItem );
                    }
                }

                // Observed data
                auto observedDataColl = oilField->observedDataCollection();
                if ( observedDataColl->allObservedSummaryData().size() > 0 )
                {
                    options.push_back( caf::PdmOptionItemInfo::createHeader( "Observed Data", true ) );

                    for ( const auto& obsData : observedDataColl->allObservedSummaryData() )
                    {
                        auto optionItem = caf::PdmOptionItemInfo( obsData->caseName(), obsData );
                        optionItem.setLevel( 1 );
                        options.push_back( optionItem );
                    }
                }
            }
        }
    }

    return options;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setSelectedCurveDefinitions( const std::vector<RiaSummaryCurveDefinition>& curveDefinitions )
{
    resetAllFields();

    std::set<RifEclipseSummaryAddress::SummaryVarCategory> categories;
    for ( const auto& curveDef : curveDefinitions )
    {
        if ( !( curveDef.summaryCase() || curveDef.isEnsembleCurve() ) ) continue;

        RimSummaryCase* summaryCase = curveDef.summaryCase();

        RifEclipseSummaryAddress summaryAddress = curveDef.summaryAddress();

        // Ignore ensemble statistics curves
        if ( summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS ) continue;

        // Select summary category if not already selected
        auto& selectedCategories = m_selectedSummaryCategories();

        if ( std::find( selectedCategories.begin(), selectedCategories.end(), summaryAddress.category() ) == selectedCategories.end() )
        {
            if ( summaryAddress.category() != RifEclipseSummaryAddress::SUMMARY_INVALID )
            {
                m_selectedSummaryCategories.v().push_back( summaryAddress.category() );
            }
            else
            {
                // Use field category as fall back category to avoid an empty list of vectors
                summaryAddress = RifEclipseSummaryAddress::fieldAddress( "" );
            }
        }

        // Select case if not already selected
        if ( curveDef.isEnsembleCurve() )
        {
            if ( curveDef.ensemble() && !m_hideEnsembles )
            {
                if ( std::find( m_selectedSources.begin(), m_selectedSources.end(), curveDef.ensemble() ) == m_selectedSources.end() )
                {
                    m_selectedSources.push_back( curveDef.ensemble() );
                }
            }
        }
        else
        {
            if ( curveDef.summaryCase() && ( !curveDef.ensemble() || m_showIndividualEnsembleCases ) )
            {
                if ( std::find( m_selectedSources.begin(), m_selectedSources.end(), curveDef.summaryCase() ) == m_selectedSources.end() )
                {
                    m_selectedSources.push_back( curveDef.summaryCase() );
                }
            }
        }

        bool isObservedDataCase = isObservedData( summaryCase );

        auto identifierAndFieldList = m_identifierFieldsMap[summaryAddress.category()];
        for ( const auto& identifierAndField : identifierAndFieldList )
        {
            bool    isVectorField = identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME;
            QString avalue = QString::fromStdString( summaryAddress.addressComponentUiText( identifierAndField->summaryIdentifier() ) );
            if ( isVectorField && isObservedDataCase )
            {
                avalue = avalue + QString( OBSERVED_DATA_AVALUE_POSTFIX );
            }

            if ( isVectorField && summaryAddress.isCalculated() )
            {
                // Append calculation id to input vector name calculated data.
                avalue = avalue + QString( ":%1" ).arg( summaryAddress.id() );
            }

            const auto& currentSelectionVector = identifierAndField->pdmField()->v();
            if ( std::find( currentSelectionVector.begin(), currentSelectionVector.end(), avalue ) == currentSelectionVector.end() )
            {
                std::vector<QString> newSelectionVector( currentSelectionVector.begin(), currentSelectionVector.end() );
                newSelectionVector.push_back( avalue );
                ( *identifierAndField->pdmField() ) = newSelectionVector;
            }
        }

        categories.insert( curveDef.summaryAddress().category() );
    }

    if ( !categories.empty() )
    {
        RifEclipseSummaryAddress::SummaryVarCategory cat = *( categories.begin() );
        m_currentSummaryCategory.setValue( cat );
    }

    m_prevCurveCount    = allCurveDefinitionsFromSelection().size();
    m_prevCurveSetCount = allCurveSetDefinitionsFromSelections().size();
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
    if ( changedField != &m_selectedSources && changedField != &m_selectedSummaryCategories && changedField != &m_currentSummaryCategory )
    {
        RifEclipseSummaryAddress::SummaryVarCategory currentCategory = m_currentSummaryCategory();
        if ( currentCategory != RifEclipseSummaryAddress::SUMMARY_INVALID )
        {
            // When a summary vector is selected, make sure the summary category for the summary vector is in the
            // selection Note that we use the size of the variant to avoid this operation when an item in unchecked

            if ( newValue.toList().size() > oldValue.toList().size() )
            {
                if ( std::find( m_selectedSummaryCategories.v().begin(), m_selectedSummaryCategories.v().end(), currentCategory ) ==
                     m_selectedSummaryCategories.v().end() )
                {
                    m_selectedSummaryCategories.v().push_back( currentCategory );
                }
            }

            if ( !newValue.toList().empty() )
            {
                auto identifierAndFieldList = m_identifierFieldsMap[currentCategory];
                for ( const auto identifierAndField : identifierAndFieldList )
                {
                    if ( identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) continue;

                    auto v = identifierAndField->pdmField()->value();
                    if ( v.empty() )
                    {
                        auto field = identifierAndField->pdmField();

                        QList<caf::PdmOptionItemInfo> options;
                        appendOptionItemsForSubCategoriesAndVectors( options, identifierAndField );

                        if ( !options.isEmpty() )
                        {
                            std::vector<QString> values;

                            auto    firstOption = options.front();
                            auto    firstValue  = firstOption.value();
                            QString valueText   = firstValue.toString();

                            values.push_back( valueText );
                            field->setValue( values );
                        }
                    }
                }
            }
        }
    }

    size_t curveCount    = allCurveDefinitionsFromSelection().size();
    size_t curveSetCount = allCurveSetDefinitionsFromSelections().size();

    if ( m_toggleChangedHandler != nullptr )
    {
        // Do nothing if the curve count and curve set count is identical
        if ( !m_multiSelectionMode || ( curveCount != m_prevCurveCount || curveSetCount != m_prevCurveSetCount ) )
        {
            m_toggleChangedHandler();

            m_prevCurveCount    = curveCount;
            m_prevCurveSetCount = curveSetCount;
        }
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RiuSummaryVectorSelectionUi::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
    QList<caf::PdmOptionItemInfo> options;

    if ( fieldNeedingOptions == &m_selectedSources )
    {
        appendOptionItemsForSources( options );
    }
    else if ( fieldNeedingOptions == &m_selectedSummaryCategories )
    {
        appendOptionItemsForCategories( options );
    }
    else
    {
        // Lookup item type input field
        auto identifierAndField = lookupIdentifierAndFieldFromFieldHandle( fieldNeedingOptions );
        appendOptionItemsForSubCategoriesAndVectors( options, identifierAndField );
    }

    return options;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
    caf::PdmUiGroup* sourcesGroup = uiOrdering.addNewGroupWithKeyword( "Sources", RiuSummaryCurveDefinitionKeywords::sources() );
    sourcesGroup->add( &m_selectedSources );

    caf::PdmUiGroup* itemTypesGroup = uiOrdering.addNewGroupWithKeyword( "Summary Types", RiuSummaryCurveDefinitionKeywords::summaryTypes() );
    itemTypesGroup->add( &m_selectedSummaryCategories );

    caf::PdmField<std::vector<QString>>* summaryiesField = nullptr;

    RifEclipseSummaryAddress::SummaryVarCategory sumCategory = m_currentSummaryCategory();
    if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_INVALID )
    {
        sumCategory = RifEclipseSummaryAddress::SUMMARY_FIELD;
    }

    if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_FIELD )
    {
        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_FIELD][0]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_AQUIFER )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryAquifer() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][0]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][1]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_NETWORK )
    {
        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_NETWORK][0]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_MISC )
    {
        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_MISC][0]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_REGION )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryRegion() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][0]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][1]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Regions" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][0]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][1]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_GROUP )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryWellGroup() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_GROUP][0]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_GROUP][1]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryWell() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][0]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][1]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryCompletion() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][0]->pdmField() );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][1]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][2]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryLgrCompletion() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][0]->pdmField() );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][1]->pdmField() );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][2]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][3]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_LGR )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryLgrWell() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][0]->pdmField() );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][1]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][2]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryWellSegment() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][0]->pdmField() );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][1]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][2]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_BLOCK )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryBlock() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][0]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][1]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR )
    {
        {
            caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( RiaDefines::summaryLgrBlock() + "s" );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][0]->pdmField() );
            myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][1]->pdmField() );
        }

        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][2]->pdmField();
    }
    else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_IMPORTED )
    {
        summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_IMPORTED][0]->pdmField();
    }

    caf::PdmUiGroup* summariesGroup = uiOrdering.addNewGroupWithKeyword( "Summaries", RiuSummaryCurveDefinitionKeywords::summaries() );
    if ( summaryiesField )
    {
        summariesGroup->add( summaryiesField );
    }

    uiOrdering.skipRemainingFields( true );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress>
    RiuSummaryVectorSelectionUi::findPossibleSummaryAddressesFromSelectedCases( const SummaryIdentifierAndField* identifierAndField ) const
{
    std::vector<SummarySource*> sources;
    for ( const auto& source : m_selectedSources.value() )
    {
        RimSummaryCase*           sumCase  = dynamic_cast<RimSummaryCase*>( source.p() );
        RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( source.p() );

        if ( sumCase )
        {
            if ( !isObservedData( sumCase ) )
            {
                sources.push_back( sumCase );
            }
        }
        else if ( ensemble )
        {
            sources.push_back( ensemble );
        }
    }
    return findPossibleSummaryAddresses( sources, identifierAndField );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress>
    RiuSummaryVectorSelectionUi::findPossibleSummaryAddressesFromSelectedObservedData( const SummaryIdentifierAndField* identifierAndField ) const
{
    std::vector<SummarySource*> obsData;
    for ( const auto& source : m_selectedSources.value() )
    {
        RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>( source.p() );

        if ( sumCase && isObservedData( sumCase ) )
        {
            obsData.push_back( sumCase );
        }
    }
    return findPossibleSummaryAddresses( obsData, identifierAndField );
}

//--------------------------------------------------------------------------------------------------
/// Returns the summary addresses that match the selected item type and input selections made in GUI
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress>
    RiuSummaryVectorSelectionUi::findPossibleSummaryAddresses( const std::vector<SummarySource*>& selectedSources,
                                                               const SummaryIdentifierAndField*   identifierAndField ) const
{
    std::set<RifEclipseSummaryAddress> addrUnion;

    auto isVectorField = identifierAndField != nullptr &&
                         identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME;
    auto controllingIdentifierAndField = identifierAndField != nullptr ? lookupControllingField( identifierAndField ) : nullptr;
    if ( !isVectorField && controllingIdentifierAndField != nullptr && controllingIdentifierAndField->pdmField()->v().size() == 0 )
    {
        return addrUnion;
    }

    for ( SummarySource* currSource : selectedSources )
    {
        std::set<RifEclipseSummaryAddress> allAddresses;

        RimSummaryCase*           currCase     = dynamic_cast<RimSummaryCase*>( currSource );
        RimSummaryCaseCollection* currEnsemble = dynamic_cast<RimSummaryCaseCollection*>( currSource );

        if ( currCase )
        {
            RifSummaryReaderInterface* reader = currCase->summaryReader();
            if ( reader ) allAddresses = reader->allResultAddresses();
        }
        else if ( currEnsemble )
        {
            allAddresses = currEnsemble->ensembleSummaryAddresses();
        }

        bool applySelections = identifierAndField == nullptr || ( !isVectorField && controllingIdentifierAndField != nullptr );
        std::vector<SummaryIdentifierAndField*> controllingFields;
        if ( applySelections )
        {
            // Build selections vector
            controllingFields = buildControllingFieldList( identifierAndField );
        }

        for ( auto& address : allAddresses )
        {
            if ( address.category() == m_currentSummaryCategory() )
            {
                bool addressSelected = applySelections ? isAddressCompatibleWithControllingFieldSelection( address, controllingFields ) : true;
                if ( addressSelected )
                {
                    addrUnion.insert( address );
                }
            }
        }
    }

    if ( m_hideHistoryVectors || m_hideDifferenceVectors )
    {
        std::set<RifEclipseSummaryAddress> filteredAddresses;

        for ( const auto& adr : addrUnion )
        {
            if ( m_hideHistoryVectors && adr.isHistoryVector() ) continue;

            if ( m_hideDifferenceVectors )
            {
                const auto diffText = RifReaderEclipseSummary::differenceIdentifier();
                if ( RiaStdStringTools::endsWith( adr.vectorName(), diffText ) ) continue;
            }

            if ( m_hideVectorsWithoutHistory )
            {
                auto candidateName = adr.vectorName() + RifReaderEclipseSummary::historyIdentifier();

                bool found = false;
                for ( const auto& ad : addrUnion )
                {
                    if ( ad.vectorName() == candidateName ) found = true;
                }

                if ( !found ) continue;
            }

            filteredAddresses.insert( adr );
        }

        addrUnion.swap( filteredAddresses );
    }

    return addrUnion;
}

//--------------------------------------------------------------------------------------------------
/// Build a list of relevant selections
//--------------------------------------------------------------------------------------------------
std::vector<SummaryIdentifierAndField*>
    RiuSummaryVectorSelectionUi::buildControllingFieldList( const SummaryIdentifierAndField* identifierAndField ) const
{
    std::vector<SummaryIdentifierAndField*> controllingFields;
    const auto&                             identifierAndFieldList = m_identifierFieldsMap.at( m_currentSummaryCategory() );
    for ( const auto& identifierAndFieldItem : identifierAndFieldList )
    {
        if ( identifierAndFieldItem == identifierAndField )
        {
            break;
        }
        controllingFields.push_back( identifierAndFieldItem );
    }
    return controllingFields;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SummaryIdentifierAndField* RiuSummaryVectorSelectionUi::lookupIdentifierAndFieldFromFieldHandle( const caf::PdmFieldHandle* pdmFieldHandle ) const
{
    for ( const auto& itemTypes : m_identifierFieldsMap )
    {
        for ( const auto& itemTypeInput : itemTypes.second )
        {
            if ( pdmFieldHandle == itemTypeInput->pdmField() )
            {
                return itemTypeInput;
            }
        }
    }
    return nullptr;
}

//--------------------------------------------------------------------------------------------------
/// Returns the Controlling pdm field info for the specified pdm field info.
/// Controlling means the field controlling the dependent field
/// If the specified pdm field info is the topmost (i.e. index is 0), nullptr is returned
//--------------------------------------------------------------------------------------------------
SummaryIdentifierAndField* RiuSummaryVectorSelectionUi::lookupControllingField( const SummaryIdentifierAndField* dependentField ) const
{
    for ( const auto& identifierAndFieldList : m_identifierFieldsMap )
    {
        int index = 0;
        for ( const auto& iaf : identifierAndFieldList.second )
        {
            if ( iaf == dependentField )
            {
                return index > 0 ? identifierAndFieldList.second[index - 1] : nullptr;
            }
            index++;
        }
    }
    return nullptr;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuSummaryVectorSelectionUi::isAddressCompatibleWithControllingFieldSelection(
    const RifEclipseSummaryAddress&                address,
    const std::vector<SummaryIdentifierAndField*>& identifierAndFieldList ) const
{
    for ( const auto& identifierAndField : identifierAndFieldList )
    {
        bool match = false;
        for ( const auto& selectedText : identifierAndField->pdmField()->v() )
        {
            if ( QString::compare( QString::fromStdString( address.addressComponentUiText( identifierAndField->summaryIdentifier() ) ),
                                   selectedText ) == 0 )
            {
                match = true;
                break;
            }
        }

        if ( !match )
        {
            return false;
        }
    }

    return true;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryVectorSelectionUi::buildAddressListFromSelections() const
{
    std::set<RifEclipseSummaryAddress> addressSet;
    for ( const auto& category : m_selectedSummaryCategories() )
    {
        if ( m_identifierFieldsMap.at( category ).size() == 0 || category == RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_INVALID )
            continue;

        const auto& identifierAndFieldList = m_identifierFieldsMap.at( category );
        std::vector<std::pair<RifEclipseSummaryAddress::SummaryIdentifierType, QString>> selectionStack;
        buildAddressListForCategoryRecursively( category, identifierAndFieldList.begin(), selectionStack, addressSet );
    }
    return addressSet;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::buildAddressListForCategoryRecursively(
    RifEclipseSummaryAddress::SummaryVarCategory                                      category,
    std::vector<SummaryIdentifierAndField*>::const_iterator                           identifierAndFieldItr,
    std::vector<std::pair<RifEclipseSummaryAddress::SummaryIdentifierType, QString>>& identifierPath,
    std::set<RifEclipseSummaryAddress>&                                               addressSet ) const

{
    for ( const auto& identifierText : ( *identifierAndFieldItr )->pdmField()->v() )
    {
        auto idText = identifierText;

        // Calculated results have a id appended. E.g. "Calculation_3 ( NORNE_ATW2013, WOPR:B-4H ):3"
        if ( ( *identifierAndFieldItr )->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME )
        {
            // Extract the calculation id
            QStringList tokens = idText.split( ":" );
            if ( tokens.size() > 1 )
            {
                QString calculationId = tokens.last();

                // Put the input vector name back together
                tokens.pop_back();
                idText = tokens.join( ":" );

                identifierPath.push_back( std::make_pair( RifEclipseSummaryAddress::INPUT_ID, calculationId ) );
            }
        }

        idText.remove( OBSERVED_DATA_AVALUE_POSTFIX );
        identifierPath.push_back( std::make_pair( ( *identifierAndFieldItr )->summaryIdentifier(), idText ) );

        if ( ( *identifierAndFieldItr )->summaryIdentifier() != RifEclipseSummaryAddress::INPUT_VECTOR_NAME )
        {
            buildAddressListForCategoryRecursively( category, std::next( identifierAndFieldItr, 1 ), identifierPath, addressSet );
        }
        else
        {
            std::map<RifEclipseSummaryAddress::SummaryIdentifierType, std::string> selectedIdentifiers;
            for ( const auto& identifier : identifierPath )
            {
                selectedIdentifiers.insert( std::make_pair( identifier.first, identifier.second.toStdString() ) );
            }
            auto address = RifEclipseSummaryAddress( category, selectedIdentifiers );
            addressSet.insert( address );
        }

        if ( !identifierPath.empty() )
        {
            identifierPath.pop_back();
        }
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::defineEditorAttribute( const caf::PdmFieldHandle* field,
                                                         QString                    uiConfigName,
                                                         caf::PdmUiEditorAttribute* attribute )
{
    caf::PdmUiTreeSelectionEditorAttribute* attrib = dynamic_cast<caf::PdmUiTreeSelectionEditorAttribute*>( attribute );
    if ( attrib )
    {
        if ( &m_selectedSummaryCategories == field )
        {
            attrib->currentIndexFieldHandle          = &m_currentSummaryCategory;
            attrib->showTextFilter                   = false;
            attrib->showToggleAllCheckbox            = false;
            attrib->setCurrentIndexWhenItemIsChecked = true;
        }

        // All tree selection editors are set in specified selection mode
        attrib->singleSelectionMode = !m_multiSelectionMode;
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::resetAllFields()
{
    m_selectedSources.clearWithoutDelete();
    m_selectedSummaryCategories = std::vector<caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>>();

    // clear all state in fields
    for ( auto& identifierAndFieldList : m_identifierFieldsMap )
    {
        for ( auto a : identifierAndFieldList.second )
        {
            a->pdmField()->v().clear();
        }
    }

    m_prevCurveCount    = 0;
    m_prevCurveSetCount = 0;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuSummaryVectorSelectionUi::isObservedData( const RimSummaryCase* sumCase ) const
{
    return dynamic_cast<const RimObservedSummaryData*>( sumCase ) != nullptr;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SummarySource*> RiuSummaryVectorSelectionUi::selectedSummarySources() const
{
    std::vector<SummarySource*> sources;

    for ( const auto& source : m_selectedSources )
    {
        sources.push_back( source );
    }

    return sources;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::appendOptionItemsForSources( QList<caf::PdmOptionItemInfo>& options ) const
{
    auto dataSourceOptions = optionsForSummaryDataSource( m_hideSummaryCases, m_hideEnsembles, m_showIndividualEnsembleCases );

    for ( auto& o : dataSourceOptions )
    {
        options.push_back( o );
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::appendOptionItemsForCategories( QList<caf::PdmOptionItemInfo>& options ) const
{
    std::vector<RifEclipseSummaryAddress::SummaryVarCategory> sortedCategoriesForUi;

    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_FIELD );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_AQUIFER );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_NETWORK );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_MISC );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION_2_REGION );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_GROUP );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_COMPLETION );
    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_BLOCK );

    if ( m_hideCalculationIncompatibleCategories )
    {
        sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_SEGMENT );
        sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_LGR );
        sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_COMPLETION_LGR );
        sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_BLOCK_LGR );
    }

    sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_IMPORTED );

    // NB SUMMARY_ENSEMBLE_STATISTICS is intentionally excluded
    // categoriesForUiDisplay.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_ENSEMBLE_STATISTICS);

    for ( auto category : sortedCategoriesForUi )
    {
        auto option = RiaOptionItemFactory::optionItemFromSummaryType( category );

        options.push_back( option );
    }
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::appendOptionItemsForSubCategoriesAndVectors( QList<caf::PdmOptionItemInfo>& options,
                                                                               SummaryIdentifierAndField*     identifierAndField ) const
{
    if ( identifierAndField == nullptr ) return;

    enum
    {
        SUM_CASES,
        OBS_DATA,
    };

    const int itemCount = OBS_DATA + 1;

    std::set<RifEclipseSummaryAddress> addrUnion[itemCount];
    addrUnion[SUM_CASES] = findPossibleSummaryAddressesFromSelectedCases( identifierAndField );
    addrUnion[OBS_DATA]  = findPossibleSummaryAddressesFromSelectedObservedData( identifierAndField );

    bool isVectorField = identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME;

    std::set<std::string> itemNames[itemCount];
    for ( int i = 0; i < itemCount; i++ )
    {
        for ( const auto& address : addrUnion[i] )
        {
            if ( address.isErrorResult() ) continue;

            auto name = address.addressComponentUiText( identifierAndField->summaryIdentifier() );
            if ( name.size() > 0 )
            {
                if ( isVectorField && address.isCalculated() )
                {
                    name += QString( ":%1" ).arg( address.id() ).toStdString();
                }
                itemNames[i].insert( name );
            }
        }
    }

    // Merge sets for all other fields than vector fields
    if ( !isVectorField )
    {
        itemNames[SUM_CASES].insert( itemNames[OBS_DATA].begin(), itemNames[OBS_DATA].end() );
        itemNames[OBS_DATA].clear();
    }

    for ( int i = 0; i < itemCount; i++ )
    {
        // Create headers only for vector fields when observed data is selected
        bool hasObservedData = itemNames[OBS_DATA].size() > 0;
        bool groupItems      = isVectorField && hasObservedData;
        if ( groupItems )
        {
            QString headerText;
            if ( i == SUM_CASES )
            {
                headerText = QString( "Simulated Data" );
            }
            else if ( i == OBS_DATA )
            {
                headerText = QString( "Observed Data" );
            }

            if ( !headerText.isEmpty() )
            {
                options.push_back( caf::PdmOptionItemInfo::createHeader( headerText, true ) );
            }
        }

        auto itemPostfix = ( isVectorField && i == OBS_DATA ) ? QString( OBSERVED_DATA_AVALUE_POSTFIX ) : QString( "" );

        // Sort numeric identifiers by numeric val
        std::vector<std::string> itemNamesVector;
        {
            switch ( identifierAndField->summaryIdentifier() )
            {
                case RifEclipseSummaryAddress::INPUT_REGION_NUMBER:
                case RifEclipseSummaryAddress::INPUT_SEGMENT_NUMBER:
                case RifEclipseSummaryAddress::INPUT_AQUIFER_NUMBER:
                {
                    std::set<int> values;
                    for ( const std::string& itemName : itemNames[i] )
                    {
                        values.insert( RiaStdStringTools::toInt( itemName ) );
                    }
                    for ( int v : values )
                    {
                        itemNamesVector.push_back( std::to_string( v ) );
                    }
                    break;
                }
                default:
                    itemNamesVector.insert( itemNamesVector.end(), itemNames[i].begin(), itemNames[i].end() );
                    break;
            }
        }

        for ( const auto& itemName : itemNamesVector )
        {
            QString displayName;

            if ( isVectorField )
            {
                std::string longVectorName = RiuSummaryQuantityNameInfoProvider::instance()->longNameFromVectorName( itemName );

                if ( longVectorName.empty() )
                {
                    displayName = QString::fromStdString( itemName );
                }
                else
                {
                    displayName = QString::fromStdString( longVectorName );
                    displayName += QString( " (%1)" ).arg( QString::fromStdString( itemName ) );
                }
            }
            else
            {
                displayName = QString::fromStdString( itemName );
            }

            auto optionItem = caf::PdmOptionItemInfo( displayName, QString::fromStdString( itemName ) + itemPostfix );
            if ( groupItems ) optionItem.setLevel( 1 );
            options.push_back( optionItem );
        }
    }
}
