import { ReadableElement } from './base';
import { isNumber } from 'lodash';
import { VariableValueType } from '../model/shared/condition/variable-value-type';
export class MeterElement extends ReadableElement {
    constructor(element, permissionChecker, variableCommunicator, variableStore, localization, signalRAppId) {
        super(element, permissionChecker, variableCommunicator, variableStore, localization, signalRAppId);
        this.cx = 0;
        this.cy = 0;
        this.offsetY = 0;
        this.valueObj = {};
        this.isNeedUpdateScale = false;
        if ((this.model.minValueType === VariableValueType.Constant && this.model.maxValueType === VariableValueType.Variable)
            || this.model.maxValueType === VariableValueType.Constant && this.model.minValueType === VariableValueType.Variable) {
            this.isNeedUpdateScale = true;
            this.updateScale();
            this.isNeedUpdateScale = false;
        }
        let mainEl$;
        if (this.model.version && this.model.version > 3) {
            mainEl$ = this.$element.find('[data-id="main"]');
            this.$handEl = this.$element.find('[data-id="hand"]');
            this.arcPath$ = this.$element.find('[data-id="arc"]');
        }
        else {
            mainEl$ = this.$element.children().eq(0);
            this.$handEl = this.$element.find('path[fill=\'red\']'); // 用g:first > path:eq(0)取handle可能因为多次封装取不到所以通过属性取handle
            this.arcPath$ = this.$element.find('g:first > g:first > path:eq(0)');
        }
        if (this.$handEl.length !== 1) {
            throw new Error('missing meter hand.');
        }
        this.mainElementTransform = mainEl$.attr('transform');
        const snapEl = Snap(this.$handEl[0]);
        const bBox = snapEl.getBBox(true);
        const radius = (bBox.x + bBox.width) / 2;
        this.cx = radius;
        this.cy = radius - bBox.x;
        this.offsetY = radius - (bBox.height / 2);
        setTimeout(() => {
            this.initFrameNode();
            this.changeStates();
        });
    }
    updateValueObj(value, variableName) {
        var _a, _b, _c;
        if (((_a = this.model.readVariable) === null || _a === void 0 ? void 0 : _a.name) === variableName) {
            this.isNeedUpdateScale = false;
            this.valueObj.value = value;
        }
        if (((_b = this.model.minVariable) === null || _b === void 0 ? void 0 : _b.name) === variableName) {
            this.isNeedUpdateScale = true;
            this.valueObj.min = value;
        }
        if (((_c = this.model.maxVariable) === null || _c === void 0 ? void 0 : _c.name) === variableName) {
            this.isNeedUpdateScale = true;
            this.valueObj.max = value;
        }
    }
    updateVariableValue(value, variableName) {
        this.updateValueObj(value, variableName);
        this.updateScale();
        const angle = this.getAngle();
        if (isNumber(angle)) {
            this.$handEl.attr('transform', this.mainElementTransform + ` translate(0,${this.offsetY}) rotate(${angle}, ${this.cx}, ${this.cy})`);
        }
    }
    initFrameNode() {
        const b = Snap(this.$element[0]).getBBox();
        this.rootElement.append('rect').attr('id', 'StateFrame').attr('width', b.width).attr('height', b.height).attr('fill', 'transparent');
    }
    updateScale() {
        if (!this.isNeedUpdateScale) {
            return;
        }
        let min = this.model.minValueType ? this.valueObj.min : this.model.min;
        let max = this.model.maxValueType ? this.valueObj.max : this.model.max;
        min = Number(min);
        max = Number(max);
        if (isNaN(min) || isNaN(max)) {
            min = MeterElement.DEFAULT_MIN_VALUE;
            max = MeterElement.DEFAULT_MAX_VALUE;
        }
        const avgSacle = ((max - min) / this.model.masterDivisionNumber).toFixed(5);
        const textElements = this.$element.find('g:first > text');
        for (let i = 0; i < textElements.length; i++) {
            const text = textElements[i];
            if (!text.innerHTML) {
                continue;
            }
            let sacleValue = ((Number(avgSacle) * i) + min).toFixed(0);
            // 整数位和小数位格式化；
            if (this.model.fractionDigits > 0) {
                sacleValue = (sacleValue / Math.pow(10, this.model.fractionDigits)).toFixed(this.model.fractionDigits);
            }
            if (!isNaN(sacleValue)) {
                text.innerHTML = sacleValue;
            }
        }
    }
    getAngle() {
        let min = this.model.minValueType ? this.valueObj.min : this.model.min;
        let max = this.model.maxValueType ? this.valueObj.max : this.model.max;
        min = Number(min);
        max = Number(max);
        if (isNaN(min) || isNaN(max)) {
            min = MeterElement.DEFAULT_MIN_VALUE;
            max = MeterElement.DEFAULT_MAX_VALUE;
        }
        if (!this.valueObj.value && isNaN(Number(this.valueObj.value))) {
            return undefined;
        }
        const value = Math.min(Math.max(this.valueObj.value || 0, min), max);
        const len = (value - min) / (max - min);
        const arcPath = Snap(this.arcPath$[0]);
        const b = arcPath.getBBox(true);
        const point = arcPath.getPointAtLength(len * arcPath.getTotalLength());
        const angle = this.directionPoint({ x: b.width / 2, y: b.height / 2 }, point);
        return angle;
    }
    directionPoint(point1, point2) {
        const a = point2.x - point1.x;
        const b = point2.y - point1.y;
        if (0 === a) {
            return 0 < b ? 90 : 0 > b ? 270 : 0;
        }
        if (0 === b) {
            return 0 < a ? 0 : 180;
        }
        if (isNaN(a) || isNaN(b)) {
            return 0;
        }
        let c = 180 * Math.atan(Math.abs(b / a)) / Math.PI;
        // eslint-disable-next-line no-unused-expressions
        0 > a ? c = 0 > b ? c + 180 : 180 - c : 0 > b && (c = 360 - c);
        return c;
    }
}
MeterElement.DEFAULT_MIN_VALUE = 0;
MeterElement.DEFAULT_MAX_VALUE = 100;
