/**
 * Copyright (c) HashiCorp, Inc.
 * SPDX-License-Identifier: BUSL-1.1
 */

import Modifier from 'ember-modifier';
import { inject as service } from '@ember/service';
import { runInDebug } from '@ember/debug';
import { registerDestructor } from '@ember/destroyable';

const typeAssertion = (type, value, withDefault) => {
  return typeof value === type ? value : withDefault;
};

function cleanup(instance) {
  if (instance && instance?.source && instance?.hash) {
    instance.source?.off('success', instance.hash.success)?.off('error', instance.hash.error);

    instance.source?.destroy();
    instance.hash = null;
    instance.source = null;
  }
}
export default class WithCopyableModifier extends Modifier {
  @service('clipboard/os') clipboard;

  hash = null;
  source = null;

  connect([value], _hash) {
    value = typeAssertion('string', value, this.element.innerText);
    const hash = {
      success: (e) => {
        runInDebug((_) => console.info(`with-copyable: Copied \`${value}\``));
        return typeAssertion('function', _hash.success, () => {})(e);
      },
      error: (e) => {
        runInDebug((_) => console.info(`with-copyable: Error copying \`${value}\``));
        return typeAssertion('function', _hash.error, () => {})(e);
      },
    };
    this.source = this.clipboard
      .execute(this.element, {
        text: (_) => value,
        container: this.element,
        ...hash.options,
      })
      .on('success', hash.success)
      .on('error', hash.error);
    this.hash = hash;
  }

  constructor() {
    super(...arguments);
    registerDestructor(this, cleanup);
  }

  modify(element, value, namedArgs) {
    this.element = element;
    this.disconnect();
    this.connect(value, namedArgs);
  }

  disconnect() {
    cleanup.call(this);
  }
}
