// src/dccQuantity.js
import { DSIUnit } from "dsiunits-js";

export class DCCQuantity {
    constructor(jsonData) {
        this.jsonData = jsonData;
    }

    getRefType() {
        return (this.jsonData.$ && this.jsonData.$.refType) ? this.jsonData.$.refType : '';
    }

    getName(language) {
        const nameData = this.jsonData['dcc:name'];
        if (!nameData) return '';
        const content = nameData['dcc:content'];
        if (Array.isArray(content)) {
            const match = content.find(item => item.$ && item.$.lang === language) || content[0];
            return match._ || match;
        }
        return content._ || content;
    }

    getConformity(language) {
        if (this.jsonData['dcc:measurementMetaData'] && this.jsonData['dcc:measurementMetaData']['dcc:metaData']) {
            let metaData = this.jsonData['dcc:measurementMetaData']['dcc:metaData'];
            if (!Array.isArray(metaData)) metaData = [metaData];
            const confMeta = metaData.find(m => m.$ && m.$.refType && m.$.refType.includes('basic_conformity'));
            if (confMeta) {
                return new DCCConformity(confMeta, language);
            }
        }
        return null;
    }
}

export class DCCRealListQuantity extends DCCQuantity {
    constructor(jsonData) {
        super(jsonData);
    }

    getValues() {
        const realList = this.jsonData['si:realListXMLList'];
        if (realList && realList['si:valueXMLList']) {
            return realList['si:valueXMLList']
                .trim()
                .split(/\s+/)
                .map(v => parseFloat(v));
        }
        return [];
    }

    getUnit(options = { oneLine: true }) {
        const realList = this.jsonData['si:realListXMLList'];
        if (realList && realList['si:unitXMLList']) {
            const rawUnit = realList['si:unitXMLList'].trim();
            const unit = new DSIUnit(rawUnit);
            return unit.toHTML(options);
        }
        return '';
    }

    getUncertainty() {
        const realList = this.jsonData['si:realListXMLList'];
        if (
            realList &&
            realList['si:measurementUncertaintyUnivariateXMLList'] &&
            realList['si:measurementUncertaintyUnivariateXMLList']['si:expandedMUXMLList'] &&
            realList['si:measurementUncertaintyUnivariateXMLList']['si:expandedMUXMLList']['si:valueExpandedMUXMLList']
        ) {
            const errStr = realList['si:measurementUncertaintyUnivariateXMLList']['si:expandedMUXMLList']['si:valueExpandedMUXMLList'];
            return errStr.trim().split(/\s+/).map(v => parseFloat(v));
        }
        return [];
    }
}

export class DCCRealQuantity extends DCCQuantity {
    constructor(jsonData) {
        super(jsonData);
    }

    getValues() {
        const realData = this.jsonData['si:real'];
        if (realData && realData['si:value']) {
            return [parseFloat(realData['si:value'])];
        }
        return [];
    }

    getUnit(options = { oneLine: true }) {
        const realData = this.jsonData['si:real'];
        if (realData && realData['si:unit']) {
            const rawUnit = realData['si:unit'].trim();
            const unit = new DSIUnit(rawUnit);
            return unit.toHTML(options);
        }
        return '';
    }

    getUncertainty() {
        const realData = this.jsonData['si:real'];
        if (
            realData &&
            realData['si:measurementUncertaintyUnivariate'] &&
            realData['si:measurementUncertaintyUnivariate']['si:expandedMU'] &&
            realData['si:measurementUncertaintyUnivariate']['si:expandedMU']['si:valueExpandedMU']
        ) {
            const errStr = realData['si:measurementUncertaintyUnivariate']['si:expandedMU']['si:valueExpandedMU'];
            return errStr.trim().split(/\s+/).map(v => parseFloat(v));
        }
        return [];
    }
}

export class DCCConformity {
    constructor(metaDataJson, defaultLanguage) {
        this.metaDataJson = metaDataJson;
        this.defaultLanguage = defaultLanguage;
    }

    getConformityValues() {
        const confList = this.metaDataJson['dcc:conformityXMLList'];
        if (confList) {
            return confList.trim().split(/\s+/);
        }
        return [];
    }

    // Helper method to select the tolerance name based on the provided language.
    _getTolerance(q, language = this.defaultLanguage) {
        if (q['dcc:name'] && q['dcc:name']['dcc:content']) {
            let content = q['dcc:name']['dcc:content'];
            if (Array.isArray(content)) {
                const match = content.find(item => item.$ && item.$.lang === language) || content[0];
                return match._ || match;
            }
            return content._ || content;
        }
        return '';
    }

    getLowerLimit(language = this.defaultLanguage) {
        const data = this.metaDataJson['dcc:data'];
        if (data && data['dcc:quantity']) {
            let quantities = data['dcc:quantity'];
            if (!Array.isArray(quantities)) quantities = [quantities];
            for (let q of quantities) {
                if (q.$ && q.$.refType && q.$.refType.includes('basic_toleranceLimitLower')) {
                    let lowerValue = null;
                    let lowerUnit = '';
                    if (q['si:realListXMLList']) {
                        const realList = q['si:realListXMLList'];
                        if (realList['si:valueXMLList']) {
                            lowerValue = parseFloat(realList['si:valueXMLList'].trim());
                        }
                        if (realList['si:unitXMLList']) {
                            const rawUnit = realList['si:unitXMLList'].trim();
                            const unit = new DSIUnit(rawUnit);
                            lowerUnit = unit.toHTML({ oneLine: true });
                        }
                    }
                    return { value: lowerValue, unit: lowerUnit, name: this._getTolerance(q, language) };
                }
            }
        }
        return null;
    }

    getUpperLimit(language = this.defaultLanguage) {
        const data = this.metaDataJson['dcc:data'];
        if (data && data['dcc:quantity']) {
            let quantities = data['dcc:quantity'];
            if (!Array.isArray(quantities)) quantities = [quantities];
            for (let q of quantities) {
                if (q.$ && q.$.refType && q.$.refType.includes('basic_toleranceLimitUpper')) {
                    let upperValue = null;
                    let upperUnit = '';
                    if (q['si:realListXMLList']) {
                        const realList = q['si:realListXMLList'];
                        if (realList['si:valueXMLList']) {
                            upperValue = parseFloat(realList['si:valueXMLList'].trim());
                        }
                        if (realList['si:unitXMLList']) {
                            const rawUnit = realList['si:unitXMLList'].trim();
                            const unit = new DSIUnit(rawUnit);
                            upperUnit = unit.toHTML({ oneLine: true });
                        }
                    }
                    return { value: upperValue, unit: upperUnit, name: this._getTolerance(q, language) };
                }
            }
        }
        return null;
    }
}