import { getOwner } from '../../-internals/owner/index.js';
import '../../debug/index.js';
import '../../-internals/meta/lib/meta.js';
import '../../../shared-chunks/mandatory-setter-CXNsxygN.js';
import { isDevelopingApp } from '@embroider/macros';
import '../../../@glimmer/destroyable/index.js';
import '../../../@glimmer/validator/index.js';
import '../../../@glimmer/manager/index.js';
import '../../../shared-chunks/cache-DtDz7X5V.js';
import '../../../shared-chunks/env-DxZ20QzS.js';
import { readOnly } from '../../object/lib/computed/computed_macros.js';
import '../../object/index.js';
import '../../object/core.js';
import '../../-internals/runtime/lib/mixins/registry_proxy.js';
import '../../-internals/runtime/lib/mixins/container_proxy.js';
import '../../-internals/runtime/lib/mixins/comparable.js';
import '../../-internals/runtime/lib/mixins/action_handler.js';
import '../../-internals/runtime/lib/mixins/-proxy.js';
import '../../enumerable/mutable.js';
import '../../-internals/runtime/lib/mixins/target_action_support.js';
import '../../-internals/runtime/lib/ext/rsvp.js';
import '../../array/index.js';
import Service from '../../service/index.js';
import EmberRouter from '../router.js';
import { ROUTER } from '../router-service.js';
import { assert } from '../../debug/lib/assert.js';

/**
@module ember
*/

class RoutingService extends Service {
  [ROUTER];
  get router() {
    let router = this[ROUTER];
    if (router !== undefined) {
      return router;
    }
    let owner = getOwner(this);
    (isDevelopingApp() && !(owner) && assert('RoutingService is unexpectedly missing an owner', owner));
    let _router = owner.lookup('router:main');
    (isDevelopingApp() && !(_router instanceof EmberRouter) && assert('ROUTING SERVICE BUG: Expected router to be an instance of EmberRouter', _router instanceof EmberRouter));
    _router.setupRouter();
    return this[ROUTER] = _router;
  }
  hasRoute(routeName) {
    return this.router.hasRoute(routeName);
  }
  transitionTo(routeName, models, queryParams, shouldReplace) {
    let transition = this.router._doTransition(routeName, models, queryParams);
    if (shouldReplace) {
      transition.method('replace');
    }
    return transition;
  }
  normalizeQueryParams(routeName, models, queryParams) {
    this.router._prepareQueryParams(routeName, models, queryParams);
  }
  _generateURL(routeName, models, queryParams) {
    let visibleQueryParams = {};
    if (queryParams) {
      Object.assign(visibleQueryParams, queryParams);
      this.normalizeQueryParams(routeName, models, visibleQueryParams);
    }
    return this.router.generate(routeName, ...models, {
      queryParams: visibleQueryParams
    });
  }
  generateURL(routeName, models, queryParams) {
    if (this.router._initialTransitionStarted) {
      return this._generateURL(routeName, models, queryParams);
    } else {
      // Swallow error when transition has not started.
      // When rendering in tests without visit(), we cannot infer the route context which <LinkTo/> needs be aware of
      try {
        return this._generateURL(routeName, models, queryParams);
      } catch (_e) {
        return;
      }
    }
  }
  isActiveForRoute(contexts, queryParams, routeName, routerState) {
    let handlers = this.router._routerMicrolib.recognizer.handlersFor(routeName);
    let leafName = handlers[handlers.length - 1].handler;
    let maximumContexts = numberOfContextsAcceptedByHandler(routeName, handlers);

    // NOTE: any ugliness in the calculation of activeness is largely
    // due to the fact that we support automatic normalizing of
    // `resource` -> `resource.index`, even though there might be
    // dynamic segments / query params defined on `resource.index`
    // which complicates (and makes somewhat ambiguous) the calculation
    // of activeness for links that link to `resource` instead of
    // directly to `resource.index`.

    // if we don't have enough contexts revert back to full route name
    // this is because the leaf route will use one of the contexts
    if (contexts.length > maximumContexts) {
      routeName = leafName;
    }
    return routerState.isActiveIntent(routeName, contexts, queryParams);
  }
}
RoutingService.reopen({
  targetState: readOnly('router.targetState'),
  currentState: readOnly('router.currentState'),
  currentRouteName: readOnly('router.currentRouteName'),
  currentPath: readOnly('router.currentPath')
});
function numberOfContextsAcceptedByHandler(handlerName, handlerInfos) {
  let req = 0;
  for (let i = 0; i < handlerInfos.length; i++) {
    req += handlerInfos[i].names.length;
    if (handlerInfos[i].handler === handlerName) {
      break;
    }
  }
  return req;
}

export { RoutingService as default };
