"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.isClipboardTransferString = isClipboardTransferString;
exports.onCopy = onCopy;
exports.onCut = onCut;
exports.onPaste = onPaste;
var _uuid = require("uuid");
var _core = require("@kui-shell/core");
var _ScrollableTerminal = require("./ScrollableTerminal");
var _BlockModel = require("./Block/BlockModel");
/*
 * Copyright 2020 The Kubernetes Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) {
  function adopt(value) {
    return value instanceof P ? value : new P(function (resolve) {
      resolve(value);
    });
  }
  return new (P || (P = Promise))(function (resolve, reject) {
    function fulfilled(value) {
      try {
        step(generator.next(value));
      } catch (e) {
        reject(e);
      }
    }
    function rejected(value) {
      try {
        step(generator["throw"](value));
      } catch (e) {
        reject(e);
      }
    }
    function step(result) {
      result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
    }
    step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
};
function isClipboardTransfer(transfer) {
  return transfer.apiVersion === 'kui-shell/v1' && transfer.kind === 'ClipboardTransfer' && Array.isArray(transfer.blocks) && transfer.blocks.length > 0;
}
function isClipboardTransferString(data) {
  try {
    return isClipboardTransfer(JSON.parse(data));
  } catch (err) {
    return false;
  }
}
/** Is this clipboard operation for me? */
function confirmTarget(me) {
  if ((0, _ScrollableTerminal.getSelectionText)().length > 0) {
    // abort if there is text selected
    return;
  }
  const isBlock = document.activeElement.classList.contains('repl-block');
  const isInput = document.activeElement.classList.contains('repl-input-element');
  if (isInput || isBlock) {
    // idx will be the insertion index
    const idx = parseInt(document.activeElement.getAttribute('data-input-count'), 10);
    const sbuuid = document.activeElement.getAttribute('data-scrollback-uuid');
    // make sure that this paste is for "us", i.e. for this Kui Tab.
    const scrollbackIdx = me.findSplit(me.state, sbuuid);
    if (scrollbackIdx >= 0) {
      // yup
      return {
        insertionIdx: idx,
        scrollbackIdx,
        execUUID: document.activeElement.getAttribute('data-uuid')
      };
    }
  }
}
/**
 * User has initiated a paste. First, we check that a block is
 * focused. We use this block to determine the insertion index. In
 * the future, we probably need to generalize this, so that we can
 * support pasting in the active block as well. Second, we make sure that
 *
 */
function onPaste(evt) {
  const target = confirmTarget(this);
  if (target) {
    // Yes, this event targets this Terminal. Now make sure that the
    // clipboard payload is a ClipboardTransfer
    try {
      const data = evt.clipboardData.getData('text');
      const transfer = JSON.parse(data);
      if (isClipboardTransfer(transfer)) {
        evt.preventDefault();
        // the target split
        const {
          uuid,
          facade
        } = this.state.splits[target.scrollbackIdx];
        // update the events to retarget them to our target split
        const execUUID = (0, _uuid.v4)();
        const retarget = {
          execUUID,
          tab: facade
        };
        // finally, fire the events off
        if ((0, _BlockModel.hasStartEvent)(transfer.blocks[0])) {
          const {
            startEvent
          } = transfer.blocks[0];
          const start = Object.assign(startEvent, retarget);
          this.onExecStart(uuid, false, start, target.insertionIdx);
        }
        if ((0, _BlockModel.isWithCompleteEvent)(transfer.blocks[0])) {
          const {
            completeEvent
          } = transfer.blocks[0];
          const complete = Object.assign(completeEvent, retarget);
          this.onExecEnd(uuid, false, complete, target.insertionIdx);
        }
      }
    } catch (err) {
      // console.error(err)
      // ok! this just means the user pasted something that isn't JSON
      // see https://github.com/IBM/kui/issues/5836
    }
  }
}
/**
 * User has initiated a clipboard copy. As with paste, we confirm
 * first that this event is relevant to `this` Terminal. If so, we
 * collect the relevant blocks, and then write a `ClipboardTransfer`
 * object to the clipboard.
 *
 */
function onCopy(evt, onSuccess) {
  const target = confirmTarget(this);
  if (target) {
    _core.Events.eventBus.emitSnapshotRequest({
      execUUID: target.execUUID,
      cb: snapshotBuffer => __awaiter(this, void 0, void 0, function* () {
        if (!snapshotBuffer) {
          console.error('Could not find the target block to copy');
          return;
        }
        const block = JSON.parse(snapshotBuffer.toString());
        if (!(0, _BlockModel.isFinished)(block)) {
          console.error('invalid snapshot', block);
          throw new Error('Invalid snapshot');
        } else {
          const blocks = [block];
          const transfer = {
            apiVersion: 'kui-shell/v1',
            kind: 'ClipboardTransfer',
            blocks
          };
          navigator.clipboard.writeText(JSON.stringify(transfer));
          if (typeof onSuccess === 'function') {
            onSuccess(target);
          }
        }
      })
    }, (0, _core.getTabId)(this.props.tab));
  }
}
/**
 * User has initated a cut. First copy. If that succeeded, the remove
 * the block.
 *
 */
function onCut(evt) {
  onCopy.bind(this)(evt, target => {
    this.state.splits[target.scrollbackIdx].willRemoveBlock(undefined, target.insertionIdx);
  });
}