{"size": 1997, "ext": "js", "max_stars_repo_path": "src/Device.js", "max_stars_repo_name": "kendratate/smartcard", "max_stars_repo_stars_event_min_datetime": "2016-04-13T00:36:49.000Z", "max_stars_repo_stars_event_max_datetime": "2021-12-23T02:00:15.000Z", "max_issues_repo_path": "src/Device.js", "max_issues_repo_name": "kendratate/smartcard", "max_issues_repo_issues_event_min_datetime": "2018-05-10T04:42:25.000Z", "max_issues_repo_issues_event_max_datetime": "2021-12-09T21:41:17.000Z", "max_forks_repo_path": "src/Device.js", "max_forks_repo_name": "kendratate/smartcard", "max_forks_repo_forks_event_min_datetime": "2016-10-25T13:56:54.000Z", "max_forks_repo_forks_event_max_datetime": "2022-02-08T08:20:11.000Z"}
{"max_stars_count": 116, "max_issues_count": 14, "max_forks_count": 44, "avg_line_length": 23.7738095238, "max_line_length": 72, "alphanum_fraction": 0.5528292439}
'use strict';

import Card from './Card';
import { EventEmitter } from 'events';
import pino from 'pino';

const logger = pino({ name: 'Device' });

class Device extends EventEmitter {
  constructor(reader) {
    super();
    logger.debug(`new Device(${reader})`);
    this.reader = reader;
    this.name = reader.name;
    this.card = null;

    const isCardInserted = (changes, reader, status) => {
      return (
        changes & reader.SCARD_STATE_PRESENT &&
        status.state & reader.SCARD_STATE_PRESENT
      );
    };

    const isCardRemoved = (changes, reader, status) => {
      return (
        changes & reader.SCARD_STATE_EMPTY &&
        status.state & reader.SCARD_STATE_EMPTY
      );
    };

    const cardInserted = (reader, status) => {
      reader.connect({ share_mode: 2 }, (err, protocol) => {
        if (err) {
          this.emit('error', err);
        } else {
          this.card = new Card(this, status.atr, protocol);
          this.emit('card-inserted', { device: this, card: this.card });
        }
      });
    };

    const cardRemoved = (reader) => {
      const name = reader.name;
      reader.disconnect(reader.SCARD_LEAVE_CARD, (err) => {
        if (err) {
          this.emit('error', err);
        } else {
          this.emit('card-removed', { name, card: this.card });
          this.card = null;
        }
      });
    };

    reader.on('status', (status) => {
      const changes = reader.state ^ status.state;
      if (changes) {
        if (isCardRemoved(changes, reader, status)) {
          cardRemoved(reader);
        } else if (isCardInserted(changes, reader, status)) {
          cardInserted(reader, status);
        }
      }
    });
  }

  transmit(data, res_len, protocol, cb) {
    try {
      this.reader.transmit(data, res_len, protocol, cb);
    } catch (err) {
      logger.warn(`transmit`, err);
    }
  }

  getName() {
    return this.name;
  }

  toString() {
    return `${this.getName()}`;
  }
}

export default Device;
