const SpiService = (posProductName,posVersion) => {
    let _spi = null;
    let _posId = window.localStorage.getItem('posID') || '';
    let _eftposAddress = window.localStorage.getItem('eftpos_address') || '192.168.1.1';
    let _spiSecrets = null;
    let _options = null;
    let _posProductName = posProductName || 'ZiiPOS';
    let _version = posVersion || '2.8.6';
    let _rcptFromEftpos = window.localStorage.getItem('rcpt_from_eftpos') === 'true';
    let _sigFlowFromEftpos = window.localStorage.getItem('check-sig-eftpos') === 'true';
    let _printMerchantCopy = window.localStorage.getItem('print_merchant_copy_input') === 'true';
    let _apiKey = window.localStorage.getItem('api_key') || '';
    let _serialNumber = window.localStorage.getItem('serial') || '';
    let _acquirerCode = window.localStorage.getItem('tenant_code') || 'wbc';
    let _autoResolveEftposAddress = window.localStorage.getItem('auto_address') === 'true';
    let _testMode = window.localStorage.getItem('test_mode') === 'true';
    let _useSecureWebSockets = window.localStorage.getItem('use_secure_web_sockets') === 'true';
    const secretsString = window.localStorage.getItem('secrets') || '';
    try {
        const secrets = JSON.parse(secretsString);
        if (secrets) {
            _spiSecrets = secrets;
        }
    } catch (err) {
        console.error('unable to access secrets');
    }

    // Where there is an existing pairing and no tenant code set, default to wbc
    if (!this._acquirerCode && this._spiSecrets) {
        this._acquirerCode = 'wbc';
        window.localStorage.setItem('tenant_code', 'wbc');
    }

    function onSpiStateChange(e, spi) {
        if (e.detail && e.detail === 'PairedConnected') {
            spi.AckFlowEndedAndBackToIdle();
        }
    };
    function onSecretsChange(e) {
        window.localStorage.setItem('secrets', JSON.stringify(e.detail));
        // Call Api to save in server
    };
    function onTerminalConfigurationChange(m) {
        const terminalConfigurationResponse = new TerminalConfigurationResponse(m);
        window.localStorage.setItem('serial', terminalConfigurationResponse.GetSerialNumber());
    };
    function onSpiTransactionUpdate(m) {
        document.dispatchEvent(new CustomEvent('TxnUpdateMessage', { detail: m }));
    };
    function onSpiResponse(e, spi) {
        spi.AckFlowEndedAndBackToIdle();
        printFlowInfo(spi);
    };
    function printFlowInfo(spi) {
        switch (spi.CurrentFlow) {
            case SpiFlow.Pairing:
                console.info(spi.CurrentPairingFlowState);
                break;
            case SpiFlow.Transaction:
                console.info(spi.CurrentTxFlowState);
                break;
            default:
                console.log('Unable to handle flow state');
        }
    }

    return {
        start() {
            try {
                _spi = new Spi(_posId, _serialNumber, _eftposAddress, _spiSecrets); // It is ok to not have the secrets yet to start with.
                _spi.Config.PromptForCustomerCopyOnEftpos = _rcptFromEftpos;
                _spi.Config.SignatureFlowOnEftpos = _sigFlowFromEftpos;
                _spi.Config.PrintMerchantCopy = _printMerchantCopy;
                _spi.SetPosInfo(_posProductName, _version);
                _spi.SetAcquirerCode(_acquirerCode);
                _spi.SetDeviceApiKey(_apiKey);
                _options = new TransactionOptions();
                _options.SetCustomerReceiptHeader(window.localStorage.getItem('receipt_header_input') || '');
                _options.SetCustomerReceiptFooter(window.localStorage.getItem('receipt_footer_input') || '');
                _options.SetMerchantReceiptHeader(window.localStorage.getItem('receipt_header_input') || '');
                _options.SetMerchantReceiptFooter(window.localStorage.getItem('receipt_footer_input') || '');
            } catch (e) {
                console.error(e.Message);
                return null;
            }
            document.addEventListener('DeviceAddressChanged', (e) => onSpiStateChange(e, _spi));
            document.addEventListener('StatusChanged', (e) => onSpiStateChange(e, spi));
            document.addEventListener('PairingFlowStateChanged', (e) => onSpiStateChange(e, _spi));
            document.addEventListener('SecretsChanged', (e) => onSecretsChange(e));
            document.addEventListener('TxFlowStateChanged', (e) => onSpiStateChange(e, _spi));
            _spi.PrintingResponse = (e) => onSpiResponse(e, _spi);
            _spi.TerminalConfigurationResponse = onTerminalConfigurationChange;
            _spi.TerminalStatusResponse = (e) => onSpiResponse(e, _spi);
            _spi.BatteryLevelChanged = (e) => onSpiResponse(e, _spi);
            _spi.TransactionUpdateMessage = onSpiTransactionUpdate;
            _spi.SetTestMode(_testMode);
            _spi.SetSecureWebSockets(_useSecureWebSockets);
            if (_autoResolveEftposAddress != null) {
                _spi.SetAutoAddressResolution(this._autoResolveEftposAddress);
            }
            _spi.Start();
            printFlowInfo(_spi);
            return _spi;
        },
    }
}