import { meta } from '../../../meta/lib/meta.js';
import Mixin from '../../../../object/mixin.js';
import { c as computed, d as defineProperty, g as get, t as tagForObject, a as tagForProperty } from '../../../../../shared-chunks/cache-DtDz7X5V.js';
import '../../../../debug/index.js';
import { updateTag as UPDATE_TAG, tagMetaFor, tagFor, combine } from '../../../../../@glimmer/validator/index.js';
import { f as setupMandatorySetter, e as isObject } from '../../../../../shared-chunks/mandatory-setter-CXNsxygN.js';
import { isDevelopingApp } from '@embroider/macros';
import { s as setProxy, i as isProxy } from '../../../../../shared-chunks/is_proxy-DxRbm8wn.js';
import { s as set } from '../../../../../shared-chunks/property_set-n9lAuzYY.js';
import '../../../../../shared-chunks/env-DxZ20QzS.js';
import { setCustomTagFor } from '../../../../../@glimmer/manager/index.js';
import { assert } from '../../../../debug/lib/assert.js';

/**
@module ember
*/

function contentFor(proxy) {
  let content = get(proxy, 'content');
  // SAFETY: Ideally we'd assert instead of casting, but @glimmer/validator doesn't give us
  // sufficient public types for this. Previously this code was .js and worked correctly so
  // hopefully this is sufficiently reliable.
  UPDATE_TAG(tagForObject(proxy), tagForObject(content));
  return content;
}
function customTagForProxy(proxy, key, addMandatorySetter) {
  (isDevelopingApp() && !(isProxy(proxy)) && assert('Expected a proxy', isProxy(proxy)));
  let meta = tagMetaFor(proxy);
  let tag = tagFor(proxy, key, meta);
  if (isDevelopingApp()) {
    // TODO: Replace this with something more first class for tracking tags in DEBUG
    // SAFETY: This is not an officially supported property but setting shouldn't cause issues.
    tag._propertyKey = key;
  }
  if (key in proxy) {
    if (isDevelopingApp() && addMandatorySetter) {
      (isDevelopingApp() && !(setupMandatorySetter) && assert('[BUG] setupMandatorySetter should be set when debugging', setupMandatorySetter));
      setupMandatorySetter(tag, proxy, key);
    }
    return tag;
  } else {
    let tags = [tag, tagFor(proxy, 'content', meta)];
    let content = contentFor(proxy);
    if (isObject(content)) {
      tags.push(tagForProperty(content, key, addMandatorySetter));
    }
    return combine(tags);
  }
}

/**
  `Ember.ProxyMixin` forwards all properties not defined by the proxy itself
  to a proxied `content` object.  See ObjectProxy for more details.

  @class ProxyMixin
  @namespace Ember
  @private
*/

const ProxyMixin = Mixin.create({
  /**
    The object whose properties will be forwarded.
     @property content
    @type {unknown}
    @default null
    @public
  */
  content: null,
  init() {
    this._super(...arguments);
    setProxy(this);
    tagForObject(this);
    setCustomTagFor(this, customTagForProxy);
  },
  willDestroy() {
    this.set('content', null);
    this._super(...arguments);
  },
  isTruthy: computed('content', function () {
    return Boolean(get(this, 'content'));
  }),
  unknownProperty(key) {
    let content = contentFor(this);
    return content ? get(content, key) : undefined;
  },
  setUnknownProperty(key, value) {
    let m = meta(this);
    if (m.isInitializing() || m.isPrototypeMeta(this)) {
      // if marked as prototype or object is initializing then just
      // defineProperty rather than delegate
      defineProperty(this, key, null, value);
      return value;
    }
    let content = contentFor(this);
    (isDevelopingApp() && !(content) && assert(`Cannot delegate set('${key}', ${value}) to the 'content' property of object proxy ${this}: its 'content' is undefined.`, content)); // SAFETY: We don't actually guarantee that this is an object, so this isn't necessarily safe :(
    return set(content, key, value);
  }
});

export { contentFor, ProxyMixin as default };
