"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getExpandedState = getExpandedState;
exports.getFocusedSourceItem = getFocusedSourceItem;
exports.getProjectDirectoryRoot = getProjectDirectoryRoot;
exports.getProjectDirectoryRootName = getProjectDirectoryRootName;
exports.getDisplayedSourcesList = exports.getSourcesTreeSources = void 0;

var _reselect = require("devtools/client/shared/vendor/reselect");

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */

/**
 * Main selector to build the SourceTree,
 * but this is also the source of data for the QuickOpen dialog.
 *
 * If no project directory root is set, this will return the thread items.
 * Otherwise this will return the items where we set the directory root.
 */
const getSourcesTreeSources = (0, _reselect.createSelector)(getProjectDirectoryRoot, state => state.sourcesTree.threadItems, (projectDirectoryRoot, threadItems) => {
  // Only accept thread which have their thread attribute set.
  // This may come late, if we receive ADD_SOURCES before INSERT_THREAD.
  // Also filter out threads which have no sources, in case we had
  // INSERT_THREAD with no ADD_SOURCES.
  threadItems = threadItems.filter(item => !!item.thread && !!item.children.length);

  if (projectDirectoryRoot) {
    const directory = getDirectoryForUniquePath(projectDirectoryRoot, threadItems);

    if (directory) {
      return directory.children;
    }

    return [];
  }

  return threadItems;
}); // This is used by QuickOpen UI

/**
 * Main selector for the QuickOpen dialog.
 *
 * The returns the list of all the reducer's source objects
 * that are possibly displayed in the Source Tree.
 * This doesn't return Source Tree Items, but the source objects.
 */

exports.getSourcesTreeSources = getSourcesTreeSources;
const getDisplayedSourcesList = (0, _reselect.createSelector)(getSourcesTreeSources, roots => {
  const sources = [];

  function walk(item) {
    if (item.type == "source") {
      sources.push(item.source);
    } else {
      for (const child of item.children) {
        walk(child);
      }
    }
  }

  for (const root of roots) {
    walk(root);
  }

  return sources;
});
exports.getDisplayedSourcesList = getDisplayedSourcesList;

function getExpandedState(state) {
  return state.sourcesTree.expanded;
}

function getFocusedSourceItem(state) {
  return state.sourcesTree.focusedItem;
}

function getProjectDirectoryRoot(state) {
  return state.sourcesTree.projectDirectoryRoot;
}

function getProjectDirectoryRootName(state) {
  return state.sourcesTree.projectDirectoryRootName;
}
/**
 * Lookup for project root item, matching the given "unique path".
 */


function getDirectoryForUniquePath(projectRoot, threadItems) {
  const sections = projectRoot.split("|");
  const thread = sections.shift();
  const threadItem = threadItems.find(item => {
    return item.uniquePath == thread || thread == "top-level" && item.thread.isTopLevel;
  });

  if (!threadItem) {
    dump(`No thread item for: ${projectRoot} -- ${thread} -- ${Object.keys(threadItems)}\n`);
    return null;
  } // If we selected a thread, the project root is for a Thread Item
  // and it only contains `${thread}`


  if (!sections.length) {
    return threadItem;
  }

  const group = sections.shift();

  for (const child of threadItem.children) {
    if (child.groupName != group) {
      continue;
    } // In case we picked a group, return it...
    // project root looked like this `${thread}|${group}`


    if (!sections.length) {
      return child;
    } // ..otherwise, we picked a directory, so look for it by traversing the tree
    // project root looked like this `${thread}|${group}|${directoryPath}`


    const path = sections.shift();
    return findPathInDirectory(child, path);
  }

  dump(` Unable to find group: ${group}\n`);
  return null;

  function findPathInDirectory(directory, path) {
    for (const child of directory.children) {
      if (child.type == "directory") {
        // `path` should be the absolute path from the group/domain
        if (child.path == path) {
          return child;
        } // Ignore folders which doesn't match the beginning of the lookup path


        if (!path.startsWith(child.path)) {
          continue;
        }

        const match = findPathInDirectory(child, path);

        if (match) {
          return match;
        }
      }
    }

    dump(`Unable to find directory: ${path}\n`);
    return null;
  }
}