//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimGeoMechPropertyFilterCollection::updateIconState()
{
    bool activeIcon = true;

    RimGeoMechView* view = NULL;
    this->firstAncestorOrThisOfType(view);
    RimViewController* viewController = view->viewController();
    if (viewController && ( viewController->isPropertyFilterOveridden() 
                            || viewController->isVisibleCellsOveridden()))
    {
        activeIcon = false;
    }

    if (!isActive)
    {
        activeIcon = false;
    }

    updateUiIconFromState(activeIcon);

    for (size_t i = 0; i < propertyFilters.size(); i++)
    {
        RimGeoMechPropertyFilter* propFilter = propertyFilters[i];
        propFilter->updateActiveState();
        propFilter->updateIconState();
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimGeoMechPropertyFilterCollection::loadAndInitializePropertyFilters()
{
    for (size_t i = 0; i < propertyFilters.size(); i++)
    {
        RimGeoMechPropertyFilter* propertyFilter = propertyFilters[i];
        propertyFilter->resultDefinition->setGeoMechCase(reservoirView()->geoMechCase());
        propertyFilter->resultDefinition->loadResult();
        propertyFilter->computeResultValueRange();
        propertyFilter->updateFieldVisibility();
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
RimGeoMechPropertyFilter* RicGeoMechPropertyFilterFeatureImpl::createPropertyFilter(RimGeoMechPropertyFilterCollection* propertyFilterCollection)
{
    CVF_ASSERT(propertyFilterCollection);

    RimGeoMechPropertyFilter* propertyFilter = new RimGeoMechPropertyFilter();
    propertyFilter->setParentContainer(propertyFilterCollection);

    setDefaults(propertyFilter);

    return propertyFilter;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
bool RimGeoMechPropertyFilterCollection::hasActiveFilters() const
{
    if (!isActive) return false;

    for (size_t i = 0; i < propertyFilters.size(); i++)
    {
        RimGeoMechPropertyFilter* propertyFilter = propertyFilters[i];
        if (propertyFilter->isActive() && propertyFilter->resultDefinition->hasResult()) return true;
    }

    return false;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimGeoMechPropertyFilterCollection::initAfterRead()
{
    for (size_t i = 0; i < propertyFilters.size(); i++)
    {
        RimGeoMechPropertyFilter* propertyFilter = propertyFilters[i];

        propertyFilter->setParentContainer(this);
        propertyFilter->resultDefinition->setGeoMechCase(reservoirView()->geoMechCase());
        propertyFilter->updateIconState();
    }

    updateIconState();
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
bool RimGeoMechPropertyFilterCollection::isUsingFormationNames() const
{
    if ( !isActive ) return false;

    for ( size_t i = 0; i < propertyFilters.size(); i++ )
    {
        RimGeoMechPropertyFilter* propertyFilter = propertyFilters[i];
        if (   propertyFilter->isActive() 
            && propertyFilter->resultDefinition->resultPositionType() == RIG_FORMATION_NAMES 
            && propertyFilter->resultDefinition->resultFieldName() != "") return true;
    }

    return false;
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RimGeoMechResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
    if(&m_resultPositionTypeUiField == changedField)
    {
        std::map<std::string, std::vector<std::string> >  fieldCompNames = getResultMetaDataForUIFieldSetting();
        QStringList uiVarNames;
        QStringList varNames;
        getUiAndResultVariableStringList(&uiVarNames, &varNames, fieldCompNames);

        if (m_resultPositionTypeUiField() == m_resultPositionType()
            && varNames.contains(composeFieldCompString(m_resultFieldName(), m_resultComponentName())))
        {
            m_resultVariableUiField = composeFieldCompString(m_resultFieldName(), m_resultComponentName());
        }
        else
        {
            m_resultVariableUiField = "";
        }

    }

    // Get the possible property filter owner
    RimGeoMechPropertyFilter* propFilter = dynamic_cast<RimGeoMechPropertyFilter*>(this->parentField()->ownerObject());
    RimView* view = NULL;
    this->firstAnchestorOrThisOfType(view);
    RimWellLogCurve* curve = NULL;
    this->firstAnchestorOrThisOfType(curve);


    if (&m_resultVariableUiField == changedField)
    {
        QStringList fieldComponentNames = m_resultVariableUiField().split(QRegExp("\\s+"));
        if (fieldComponentNames.size() > 0)
        {
            m_resultPositionType = m_resultPositionTypeUiField;
            m_resultFieldName = fieldComponentNames[0];
            if (fieldComponentNames.size() > 1)
            {
                m_resultComponentName = fieldComponentNames[1];
            }
            else
            {
                m_resultComponentName = "";
            }


            if (m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded(this->resultAddress()))
            {
                if (view) view->hasUserRequestedAnimation = true;
            }
            
            if (propFilter)
            {
                propFilter->setToDefaultValues();

                if (view) view->scheduleGeometryRegen(PROPERTY_FILTERED);
            }

            if (view) view->scheduleCreateDisplayModelAndRedraw();

            if (dynamic_cast<RimGeoMechCellColors*>(this))
            {
                if (view)
                {
                    RimViewLinker* viewLinker = view->assosiatedViewLinker();
                    if (viewLinker)
                    {
                        viewLinker->updateCellResult();
                    }
                }
            }

            if (curve)
            {
                curve->updatePlotData();
            }
        }
    }
      
    if (propFilter)
    {
        propFilter->updateConnectedEditors();
    }

    if (curve)
    {
        curve->updateConnectedEditors();
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void RivFemElmVisibilityCalculator::computePropertyVisibility(cvf::UByteArray* cellVisibility, 
                                                              const RigFemPart* grid, 
                                                              int timeStepIndex, 
                                                              const cvf::UByteArray* rangeFilterVisibility, 
                                                              RimGeoMechPropertyFilterCollection* propFilterColl)
{
    CVF_ASSERT(cellVisibility != NULL);
    CVF_ASSERT(rangeFilterVisibility != NULL);
    CVF_ASSERT(propFilterColl != NULL);

    CVF_ASSERT(grid->elementCount() > 0);
    CVF_ASSERT(rangeFilterVisibility->size() == static_cast<size_t>(grid->elementCount()));

    // Copy if not equal
    if (cellVisibility != rangeFilterVisibility ) (*cellVisibility) = *rangeFilterVisibility;
    const int elementCount = grid->elementCount();

    if (propFilterColl->hasActiveFilters())
    {
        for (size_t i = 0; i < propFilterColl->propertyFilters().size(); i++)
        {
            RimGeoMechPropertyFilter* propertyFilter = propFilterColl->propertyFilters()[i];

            if (propertyFilter->isActive() && propertyFilter->resultDefinition->hasResult())
            {
                const double lowerBound = propertyFilter->lowerBound();
                const double upperBound = propertyFilter->upperBound();

                RigFemResultAddress resVarAddress = propertyFilter->resultDefinition->resultAddress();

                size_t adjustedTimeStepIndex = timeStepIndex;

                const RimCellFilter::FilterModeType filterType = propertyFilter->filterMode();

                RigGeoMechCaseData* caseData = propFilterColl->reservoirView()->geoMechCase()->geoMechData();

                const std::vector<float>& resVals = caseData->femPartResults()->resultValues(resVarAddress, 
                                                                                             grid->elementPartId(), 
                                                                                             timeStepIndex);
                #pragma omp parallel for schedule(dynamic)
                for (int cellIndex = 0; cellIndex < elementCount; cellIndex++)
                {
                    if ( (*cellVisibility)[cellIndex] )
                    {
                        RigElementType eType = grid->elementType(cellIndex);
                        int elmNodeCount = RigFemTypes::elmentNodeCount(eType);

                        const int* elmNodeIndices = grid->connectivities(cellIndex);
                        for(int enIdx = 0; enIdx < elmNodeCount; ++enIdx)
                        {
                            size_t resultValueIndex = cvf::UNDEFINED_SIZE_T;
                            if (resVarAddress.resultPosType == RIG_NODAL)
                            {
                                resultValueIndex = elmNodeIndices[enIdx];
                            }
                            else
                            {
                                resultValueIndex = grid->elementNodeResultIdx(cellIndex, enIdx);
                            }

                            double scalarValue = resVals[resultValueIndex];
                            if (lowerBound <= scalarValue && scalarValue <= upperBound)
                            {
                                if (filterType == RimCellFilter::EXCLUDE)
                                {
                                    (*cellVisibility)[cellIndex] = false;
                                }
                            }
                            else
                            {
                                if (filterType == RimCellFilter::INCLUDE)
                                {
                                    (*cellVisibility)[cellIndex] = false;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}