import { BitSwitchOperation } from '../../model';
import { VariableStateEnum } from '../../communication';
import { Binary } from '../../model/shared/binary';
import { VariableUtil } from '../../utils/variable-util';
import { VariableDefinition } from '../../communication/variable/variable-definition';
export class BitSwitchOperator {
    constructor(settings, variableCommunicator, variableStore, signalRAppId) {
        this.settings = settings;
        this.variableCommunicator = variableCommunicator;
        this.variableStore = variableStore;
        this.signalRAppId = signalRAppId;
        if (!this.settings) {
            throw new Error('settings cannot be null');
        }
        if (this.settings.isWriteOnly) {
            this.canExecuteInternal = true;
        }
        else {
            variableCommunicator.openVariable(this.variableName, this.signalRAppId).subscribe(value => {
                this.currentValue = value;
                this.canExecuteInternal = this.currentValue && this.currentValue.state === VariableStateEnum.DataNormal;
            });
        }
    }
    get variableName() {
        const variable = new VariableDefinition(this.settings.variableName, this.settings.variableGroupName, this.settings.dataSourceCode, this.settings.variableVersion);
        return VariableUtil.getConvertedVariableName(this.variableStore, variable);
    }
    canExecute() {
        return this.canExecuteInternal;
    }
    execute() {
        if (!this.canExecute()) {
            throw new Error('Can not execute.');
        }
        const settings = this.settings;
        let newValue;
        let maxBitIndex;
        if (settings.isBitwiseIndex) {
            maxBitIndex = 31;
            this.binary = new Binary(this.currentValue.value, maxBitIndex + 1);
        }
        switch (+settings.operation) {
            case BitSwitchOperation.On:
                newValue = 1;
                if (settings.isBitwiseIndex) {
                    this.variableCommunicator.writeWordByBit(this.variableName, settings.bitIndex, newValue).subscribe();
                }
                else {
                    this.variableCommunicator.write(this.variableName, newValue).subscribe();
                }
                break;
            case BitSwitchOperation.Off:
                newValue = 0;
                if (settings.isBitwiseIndex) {
                    this.variableCommunicator.writeWordByBit(this.variableName, settings.bitIndex, newValue).subscribe();
                }
                else {
                    this.variableCommunicator.write(this.variableName, newValue).subscribe();
                }
                break;
            case BitSwitchOperation.Inverse:
                if (!this.settings.isWriteOnly) {
                    newValue = this.currentValue.value === 0 ? 1 : 0;
                    if (settings.isBitwiseIndex) {
                        let wordByBitValue = Number(this.binary.convertToBinary().substr(maxBitIndex - this.settings.bitIndex, 1));
                        wordByBitValue = wordByBitValue === 0 ? 1 : 0;
                        this.variableCommunicator.writeWordByBit(this.variableName, settings.bitIndex, wordByBitValue).subscribe();
                    }
                    else {
                        this.variableCommunicator.write(this.variableName, newValue).subscribe();
                    }
                }
                break;
            case BitSwitchOperation.Restoration:
                break;
            default:
                throw new Error(`Unknown BitSwitchOperation:${settings.operation}`);
        }
        let originValue;
        if (this.currentValue && this.currentValue.value !== undefined) {
            originValue = this.currentValue.value;
        }
        return Promise.resolve({
            variableName: this.variableName,
            originValue: originValue,
            newValue: newValue
        });
    }
    writeValue(value) {
        if (this.settings.isBitwiseIndex) {
            this.variableCommunicator.writeWordByBit(this.variableName, this.settings.bitIndex, value).subscribe();
        }
        else {
            this.variableCommunicator.write(this.variableName, value).subscribe();
        }
        let originValue;
        if (this.currentValue && this.currentValue.value !== undefined) {
            originValue = this.currentValue.value;
        }
        return Promise.resolve({
            variableName: this.variableName,
            originValue: originValue,
            newValue: value
        });
    }
}
