"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.viewer = exports.findFile = exports.findFileWithViewer = exports.isSpecialDirectory = void 0;

var _debug = _interopRequireDefault(require("debug"));

var _path = require("path");

var _home = _interopRequireDefault(require("../util/home"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/*
 * Copyright 2017-19 IBM Corporation
 *
 * 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.
 */
const debug = (0, _debug.default)('core/find-file');
debug('loading');
const specialPaths = []; // any special paths added via self.addPath

const defaultSpecial = {
  prefix: '',
  filepath: (0, _path.join)(__dirname, '..')
}; // default special is the app/ top-level

/**
 * If original has a trailing slash, make sure resolved has one, too
 *
 */

const withMatchingTrailingSlash = (original, resolved) => {
  if (original.charAt(original.length - 1) === '/' && resolved.charAt(resolved.length - 1) !== '/') {
    return `${resolved}/`;
  } else {
    return resolved;
  }
};
/**
 * Is this a special @ directory?
 *
 */


const isSpecialDirectory = filepath => (0, _path.basename)(filepath).charAt(0) === '@';
/**
 * Behaves like `findFile` with an extra call to `commandPrefix`
 *
 */


exports.isSpecialDirectory = isSpecialDirectory;

const findFileWithViewer = (filepath, {
  safe = false,
  keepRelative = false
} = {}) => {
  if (!filepath) {
    if (!safe) {
      throw new Error('Please specify a file');
    } else {
      // caller asked us to play nice
      return {
        resolved: ''
      };
    }
  } else if (filepath.charAt(0) === '@') {
    // the === '.' part handles the case where the call was e.g. findFile('@demos'), i.e. the special dir itself
    const desiredPrefix = filepath.endsWith('/') ? filepath.slice(0, filepath.length - 1) : (0, _path.dirname)(filepath) === '.' ? filepath : (0, _path.dirname)(filepath);
    const longestMatchingSpecial = specialPaths.filter(({
      prefix
    }) => filepath === prefix || desiredPrefix.indexOf(prefix) === 0).sort((a, b) => b.prefix.length - a.prefix.length)[0];
    const special = longestMatchingSpecial || defaultSpecial;
    debug('resolving @ file', filepath, desiredPrefix, special);
    return {
      resolved: withMatchingTrailingSlash(filepath, (0, _path.join)(special.filepath, filepath)),
      viewer: special.command
    };
  } else if (keepRelative) {
    return {
      resolved: filepath
    };
  } else {
    debug('resolving normal file', filepath);
    return {
      resolved: withMatchingTrailingSlash(filepath, (0, _path.resolve)((0, _home.default)(filepath)))
    };
  }
};
/**
 * Resolve @ and ~ files
 *
 * @param safe throw and exception if the file is not found
 * @param keepRelative don't expand ~
 */


exports.findFileWithViewer = findFileWithViewer;

const findFile = (filepath, {
  safe = false,
  keepRelative = false
} = {}) => {
  return findFileWithViewer(filepath, {
    safe,
    keepRelative
  }).resolved;
};
/**
 * Does the given special have an associated command prefix that is
 * used to view files in that special directory?
 *
 * @param special a registered prefix of an `ISpecialPath`
 * @return the registered command prefix used to view files in this special directory, if any
 */


exports.findFile = findFile;

const viewer = prefix => {
  const special = specialPaths.find(_ => _.prefix === prefix);

  if (!special) {
    throw new Error('bad special prefix');
  } else {
    return special.command || undefined;
  }
};

exports.viewer = viewer;