var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Injectable } from '@angular/core';
import { NumericalOperationType } from './numerical-operation-type';
import { DataTypeService } from './data-type/data-type.service';
let NumericalOperationService = class NumericalOperationService {
    constructor(dataTypeService) {
        this.dataTypeService = dataTypeService;
    }
    getNumericalOperationedValue(model, value, fractionDigits) {
        let operationedValue = value;
        const numericalOperationSetting = model.numericalOperationSetting;
        // 比例转换
        // 显示值= (比例上限-比例下限) / (数值上限-数值下限) * (PLC值-数值下限) + 比例下限
        if (numericalOperationSetting.type === NumericalOperationType.ProportionalConversion) {
            const proportionalUpperLimit = numericalOperationSetting.settings.upperLimit;
            const proportionalLowerLimit = numericalOperationSetting.settings.lowerLimit;
            const numericalUpperLimit = model.numericalUpperLimit;
            const numericalLowerLimit = model.numericalLowerLimit;
            if (numericalUpperLimit === numericalLowerLimit) {
                return operationedValue;
            }
            const displayValue = (proportionalUpperLimit - proportionalLowerLimit)
                / (numericalUpperLimit - numericalLowerLimit) * (value - numericalLowerLimit)
                + proportionalLowerLimit;
            operationedValue = displayValue.toFixed(fractionDigits);
        }
        else if (numericalOperationSetting.type === NumericalOperationType.Zoom) {
            // 显示值= (PLC值*增益) +偏移量
            const gain = numericalOperationSetting.settings.gain;
            const offset = numericalOperationSetting.settings.offset;
            const displayValue = value * gain + offset;
            operationedValue = displayValue.toFixed(fractionDigits);
        }
        return operationedValue;
    }
    getNumericalOperations(model) {
        const numericalOperation = {};
        numericalOperation.numericalUpperLimit = (model.numericalUpperLimit || model.numericalUpperLimit === 0) ? +model.numericalUpperLimit
            : this.dataTypeService.getMaxValue(model.version, model.dataType, model.fBoxDataType, model.integerDigits, model.fractionDigits);
        numericalOperation.numericalLowerLimit = (model.numericalLowerLimit || model.numericalLowerLimit === 0) ? +model.numericalLowerLimit
            : this.dataTypeService.getMinValue(model.version, model.dataType, model.fBoxDataType, model.integerDigits, model.fractionDigits);
        numericalOperation.enableNumericalOperation = model.enableNumericalOperation;
        if (model.enableNumericalOperation) {
            numericalOperation.type = model.numericalOperationSetting.type;
            if (numericalOperation.type === NumericalOperationType.ProportionalConversion) {
                numericalOperation.proportionalConversion = {};
                numericalOperation.proportionalConversion.lowerLimit = model.numericalOperationSetting.settings.lowerLimit;
                numericalOperation.proportionalConversion.upperLimit = model.numericalOperationSetting.settings.upperLimit;
            }
            else if (numericalOperation.type === NumericalOperationType.Zoom) {
                numericalOperation.zoom = {};
                numericalOperation.zoom.gain = model.numericalOperationSetting.settings.gain;
                numericalOperation.zoom.offset = model.numericalOperationSetting.settings.offset;
            }
        }
        return numericalOperation;
    }
    getWriteValue(version, value, option, dataType, fractionDigits) {
        const displayValue = Number(value);
        let writeValue = Number(value);
        // 比例转换
        // PLC值 = （显示值 - 比例下限）*(数值上限-数值下限) /(比例上限-比例下限) + 数值下限
        if (option.type === NumericalOperationType.ProportionalConversion) {
            const proportionalUpperLimit = option.proportionalConversion.upperLimit;
            const proportionalLowerLimit = option.proportionalConversion.lowerLimit;
            const numericalUpperLimit = option.numericalUpperLimit;
            const numericalLowerLimit = option.numericalLowerLimit;
            if (proportionalUpperLimit === proportionalLowerLimit) {
                return writeValue.toString();
            }
            writeValue = (displayValue - proportionalLowerLimit) * (numericalUpperLimit - numericalLowerLimit)
                / (proportionalUpperLimit - proportionalLowerLimit)
                + numericalLowerLimit;
        }
        else if (option.type === NumericalOperationType.Zoom) {
            // PLC值 = （显示值-偏移量）/增益
            const gain = option.zoom.gain;
            const offset = option.zoom.offset;
            if (gain === 0) {
                return writeValue.toString();
            }
            writeValue = (displayValue - offset) / gain;
        }
        if (this.dataTypeService.isFloat(version, dataType)) {
            writeValue = Number(writeValue.toFixed(fractionDigits));
        }
        else {
            writeValue = Number(writeValue.toFixed(0));
        }
        return writeValue.toString();
    }
    getWriteMaxValue(numericalUpperLimit, option) {
        // 校验数值范围
        let maxValueLimit = numericalUpperLimit;
        if (option.enableNumericalOperation) {
            if (option.type === NumericalOperationType.ProportionalConversion) {
                maxValueLimit = option.proportionalConversion.upperLimit;
            }
            else if (option.type === NumericalOperationType.Zoom) {
                // 显示值= (PLC值*增益) +偏移量
                const gain = option.zoom.gain;
                const offset = option.zoom.offset;
                const perationGain = this.toInteger(gain);
                maxValueLimit = maxValueLimit * perationGain.num / perationGain.times + offset;
            }
        }
        return maxValueLimit;
    }
    getWriteMinValue(numericalLowerLimit, option) {
        // 校验数值范围
        let minValueLimit = numericalLowerLimit;
        if (option.enableNumericalOperation) {
            if (option.type === NumericalOperationType.ProportionalConversion) {
                minValueLimit = option.proportionalConversion.lowerLimit;
            }
            else if (option.type === NumericalOperationType.Zoom) {
                // 显示值= (PLC值*增益) +偏移量
                const gain = option.zoom.gain;
                const offset = option.zoom.offset;
                const perationGain = this.toInteger(gain);
                minValueLimit = minValueLimit * perationGain.num / perationGain.times + offset;
            }
        }
        return minValueLimit;
    }
    /*
    * 将一个浮点数转成整数，返回整数和倍数。如 3.14 >> 314，倍数是 100
    * @param floatNum {number} 小数
    * @return {object}
    *   {times:100, num: 314}
    */
    toInteger(floatNum) {
        const ret = { times: 1, num: 0 };
        const isNegative = floatNum < 0 ? true : false;
        floatNum = Math.abs(floatNum);
        if (this.isInteger(floatNum)) {
            ret.num = floatNum;
            if (isNegative) {
                ret.num = -floatNum;
            }
            else {
                ret.num = floatNum;
            }
            return ret;
        }
        const strfi = floatNum + '';
        const dotPos = strfi.indexOf('.');
        const len = strfi.substr(dotPos + 1).length;
        const times = Math.pow(10, len);
        const intNum = parseInt((floatNum * times + 0.5).toString(), 10);
        ret.times = times;
        ret.num = intNum;
        if (isNegative) {
            ret.num = -intNum;
        }
        else {
            ret.num = intNum;
        }
        return ret;
    }
    isInteger(obj) {
        return Math.floor(obj) === obj;
    }
};
NumericalOperationService = __decorate([
    Injectable(),
    __metadata("design:paramtypes", [DataTypeService])
], NumericalOperationService);
export { NumericalOperationService };
