void FeatureLayerDrawer::setActiveVisualAttribute(const QString &attr)
{
    IFeatureCoverage features = coverage().as<FeatureCoverage>();
    if ( features.isValid())    {
        if ( features->attributeDefinitions().columnIndex(attr) != iUNDEF){

            IRepresentation newrpr = Representation::defaultRepresentation(features->attributeDefinitions().columndefinition(attr).datadef().domain());
            if ( newrpr.isValid()){
                LayerDrawer::setActiveVisualAttribute(attr);
            }
        }
    }
}
void FeatureLayerDrawer::resetVisualProperty(const QString& propertyName, const IRepresentation& rpr){
   IFeatureCoverage features = coverage().as<FeatureCoverage>();
    for(int i = 0; i < features->attributeDefinitions().definitionCount(); ++i){
        const ColumnDefinition& coldef = features->attributeDefinitions().columndefinitionRef(i);
        if ( coldef.name() == propertyName){
            IlwisTypes attrType = coldef.datadef().domain()->ilwisType();
            if ( hasType(attrType, itNUMERICDOMAIN | itITEMDOMAIN | itTEXTDOMAIN)){
                VisualAttribute props = createVisualProperty(coldef, i, rpr);
                visualProperty(coldef.name(), props);
                break;
            }
        }
    }
}
QString IlwisObjectModel::valuetype() const
{
    try{
        if ( !_ilwisobject.isValid())
            return "";

        IlwisTypes objectype = _ilwisobject->ilwisType();
        IlwisTypes valueType = itUNKNOWN;
        if ( hasType( objectype, itCOVERAGE|itDOMAIN)){
            if ( objectype == itRASTER){
                IRasterCoverage raster = _ilwisobject.as<RasterCoverage>();
                valueType = raster->datadef().domain()->valueType();
            } else if ( hasType( objectype , itFEATURE)){
                IFeatureCoverage features = _ilwisobject.as<FeatureCoverage>();
                ColumnDefinition coldef = features->attributeDefinitions().columndefinition(COVERAGEKEYCOLUMN);
                if ( coldef.isValid()){
                    valueType = coldef.datadef().domain()->valueType();
                }

            } else if ( hasType( objectype , itDOMAIN)){
                IDomain dom = _ilwisobject.as<Domain>();
                valueType = dom->valueType();

            }
        }
        QString typeName =  TypeHelper::type2HumanReadable(valueType);

        return typeName == sUNDEF ? "" : typeName;
    }catch(const ErrorObject& ){
        // no exceptions may escape here
    }
    return "";
}
void IlwisObjectModel::resetAttributeModel(const QString& attributeName){

    auto setAttributeModel = [&](int i, const ColumnDefinition& coldef, const QString& attributeName){
        if ( coldef.name() == attributeName){
            AttributeModel *attribute = new AttributeModel(coldef, this, _ilwisobject);
            _attributes[i] = attribute;
        }
    };

    IlwisTypes objecttype = _ilwisobject->ilwisType();
    if ( objecttype == itRASTER){
        IRasterCoverage raster = _ilwisobject.as<RasterCoverage>();
        if ( raster->hasAttributes()){
            for(int i = 0; i < raster->attributeTable()->columnCount(); ++i){
                setAttributeModel(i,raster->attributeTable()->columndefinition(i), attributeName);
            }
        }
    } else if ( hasType(objecttype,itFEATURE)){
        IFeatureCoverage features = _ilwisobject.as<FeatureCoverage>();
        for(int i = 0; i < features->attributeDefinitions().definitionCount(); ++i){
            setAttributeModel(i,features->attributeTable()->columndefinition(i), attributeName);
        }
    } else if ( hasType(objecttype,itTABLE)){
        ITable tbl = _ilwisobject.as<Table>();
        for(int i = 0; i < tbl->columnCount(); ++i){
            setAttributeModel(i,tbl->columndefinition(i),attributeName);
        }
    }

}
QQmlListProperty<AttributeModel> IlwisObjectModel::attributes()
{
    try {
        if ( _attributes.size() == 0){
            if ( _ilwisobject.isValid())    {
                IlwisTypes objecttype = _ilwisobject->ilwisType();
                if ( objecttype == itRASTER){
                    IRasterCoverage raster = _ilwisobject.as<RasterCoverage>();

                    if ( raster->hasAttributes()){
                        for(int i = 0; i < raster->attributeTable()->columnCount(); ++i){
                            AttributeModel *attribute = new AttributeModel(raster->attributeTable()->columndefinition(i), this, _ilwisobject);
                            _attributes.push_back(attribute);
                        }
                    }else {
                        AttributeModel *attribute = new AttributeModel(ColumnDefinition(PIXELVALUE, raster->datadef(),i64UNDEF), this, _ilwisobject);
                        _attributes.push_back(attribute);
                    }
                } else if ( hasType(objecttype,itFEATURE)){
                    IFeatureCoverage features = _ilwisobject.as<FeatureCoverage>();
                    for(int i = 0; i < features->attributeDefinitions().definitionCount(); ++i){
                        AttributeModel *attribute = new AttributeModel(features->attributeDefinitions().columndefinition(i), this, _ilwisobject);
                        _attributes.push_back(attribute);
                    }
                } else if ( hasType(objecttype,itTABLE)){
                    ITable tbl = _ilwisobject.as<Table>();
                    for(int i = 0; i < tbl->columnCount(); ++i){
                        AttributeModel *attribute = new AttributeModel(tbl->columndefinition(i), this, _ilwisobject);
                        _attributes.push_back(attribute);
                    }
                }
            }
        }
        if ( _attributes.size() > 0){
            return QQmlListProperty<AttributeModel>(this, _attributes) ;
        }
    }
    catch(const ErrorObject& ){
        // no exceptions may escape here
    }
    return QQmlListProperty<AttributeModel>();

}
void FeatureLayerDrawer::coverage(const ICoverage &cov)
{
    LayerDrawer::coverage(cov);
    setActiveVisualAttribute(sUNDEF);
    IFeatureCoverage features = coverage().as<FeatureCoverage>();

    for(int i = 0; i < features->attributeDefinitions().definitionCount(); ++i){
        const ColumnDefinition& coldef = features->attributeDefinitions().columndefinitionRef(i);
        IlwisTypes attrType = coldef.datadef().domain()->ilwisType();
        if ( hasType(attrType, itNUMERICDOMAIN | itITEMDOMAIN | itTEXTDOMAIN)){
            VisualAttribute props = createVisualProperty(coldef, i);
            visualProperty(coldef.name(), props);
        }
    }
    // try to find a reasonable default for the activeattribute
    for(int i = 0; i < features->attributeDefinitions().definitionCount(); ++i){
        if ( activeAttribute() == sUNDEF){
            const ColumnDefinition& coldef = features->attributeDefinitions().columndefinitionRef(i);
            if ( features->attributeDefinitions().columnIndex(FEATUREVALUECOLUMN) != iUNDEF){
                setActiveVisualAttribute(FEATUREVALUECOLUMN);
            }else if ( features->attributeDefinitions().columnIndex(COVERAGEKEYCOLUMN) != iUNDEF){
                setActiveVisualAttribute(COVERAGEKEYCOLUMN);
            }
            else if ( hasType(coldef.datadef().domain()->ilwisType(), itNUMERICDOMAIN)){
                setActiveVisualAttribute(coldef.name());
            }
        }else
            break;
    }
}
QString IlwisObjectModel::rangeDefinition(bool defaultRange, bool calc, const QString& columnName) {
    try {
        IlwisTypes objectype = _ilwisobject->ilwisType();
        QString rangeString;
        if ( hasType( objectype, itCOVERAGE|itDOMAIN)){
            if ( objectype == itRASTER){
                IRasterCoverage raster = _ilwisobject.as<RasterCoverage>();
                if ( defaultRange){
                  rangeString = raster->datadef().domain()->range()->toString();
                }else{
                    if ( calc){
                        raster->loadData();
                        raster->statistics(NumericStatistics::pBASIC);
                    }
                  rangeString = raster->datadef().range()->toString();
                }
            } else if ( hasType( objectype , itFEATURE)){
                IFeatureCoverage features = _ilwisobject.as<FeatureCoverage>();
                ColumnDefinition coldef = features->attributeDefinitions().columndefinition(COVERAGEKEYCOLUMN);
                if ( coldef.isValid()){
                    if ( defaultRange)
                      rangeString =  coldef.datadef().domain()->range()->toString();
                    else{
                        if ( calc){
                            features->loadData();
                            std::vector<QVariant> data = features->attributeTable()->column(columnName);
                            if ( data.size() != 0){
                                std::vector<double> values(data.size());
                                int  i=0;
                                for(auto v : data)
                                    values[i++] = v.toDouble();
                                NumericStatistics stats; // realy like to do this with a template specialization of the proper calculate function, but the syntax was unclear to me
                                stats.calculate(values.begin(), values.end());
                                NumericRange *rng = new NumericRange(stats.prop(NumericStatistics::pMIN),stats.prop(NumericStatistics::pMAX));
                                features->attributeDefinitionsRef().columndefinitionRef(columnName).datadef().range(rng);
                            }
                        }
                        rangeString = coldef.datadef().range()->toString();
                    }
                }

            } else if ( hasType( objectype , itDOMAIN)){
                rangeString = _ilwisobject.as<Domain>()->range()->toString();
            }
        }
        return rangeString;
    }catch(const ErrorObject& ){
        // no exceptions may escape here
    }
    return "";

}
QString IlwisObjectModel::value2string(const QVariant &value, const QString &attrName)
{
    auto v2s = [](const ColumnDefinition& coldef, const QVariant& value)->QString {
            if ( coldef.isValid()){
                if ( coldef.datadef().domain()->ilwisType() == itTEXTDOMAIN)
                    return value.toString();
                return coldef.datadef().domain()->impliedValue(value).toString();
            }
            if ( value.toDouble() == rUNDEF)
                return sUNDEF;
            return value.toString();
    };
    if ( attrName != "") {
        IlwisTypes objectype = _ilwisobject->ilwisType();
        if ( hasType(objectype, itFEATURE)){
            IFeatureCoverage features = _ilwisobject.as<FeatureCoverage>();
            ColumnDefinition coldef = features->attributeDefinitions().columndefinition(attrName);
            return v2s(coldef, value);

        }else if (hasType(objectype, itRASTER)){
             IRasterCoverage raster = _ilwisobject.as<RasterCoverage>();
             if ( raster->hasAttributes()){
                ColumnDefinition coldef = raster->attributeTable()->columndefinition(attrName);
                return v2s(coldef, value);
             }
             if ( raster->datadef().domain()->ilwisType() == itCOLORDOMAIN){
                 auto clr = ColorRangeBase::toColor(value, ColorRangeBase::cmRGBA);
                return ColorRangeBase::toString(clr,ColorRangeBase::cmRGBA)    ;
             }
        }
    }
    if ( value.toDouble() == rUNDEF)
        return sUNDEF;
    return value.toString();

}