/**
 * @license
 * Copyright Google LLC All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
import '../zone.umd.js';
const testClosureFunction = () => {
  const logs: string[] = [];
  // call all Zone exposed functions
  const testZoneSpec: ZoneSpec = {
    name: 'closure',
    properties: {},
    onFork:
        (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
         zoneSpec: ZoneSpec) => {
          return parentZoneDelegate.fork(targetZone, zoneSpec);
        },

    onIntercept:
        (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function,
         source: string) => {
          return parentZoneDelegate.intercept(targetZone, delegate, source);
        },

    onInvoke: function(
        parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function,
        applyThis?: any, applyArgs?: any[], source?: string) {
      return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source);
    },

    onHandleError: function(
        parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any) {
      return parentZoneDelegate.handleError(targetZone, error);
    },

    onScheduleTask: function(
        parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) {
      return parentZoneDelegate.scheduleTask(targetZone, task);
    },

    onInvokeTask: function(
        parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task,
        applyThis?: any, applyArgs?: any[]) {
      return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs);
    },

    onCancelTask: function(
        parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) {
      return parentZoneDelegate.cancelTask(targetZone, task);
    },

    onHasTask: function(
        delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) {
      return delegate.hasTask(target, hasTaskState);
    }
  };

  Zone.__load_patch('test_closure_load_patch', function() {});
  Zone.__symbol__('test_symbol');

  const testZone: Zone = Zone.current.fork(testZoneSpec);
  testZone.runGuarded(() => {
    testZone.run(() => {
      const properties = testZoneSpec.properties;
      properties!['key'] = 'value';
      const keyZone = Zone.current.getZoneWith('key');

      logs.push('current' + Zone.current.name);
      logs.push('parent' + Zone.current.parent!.name);
      logs.push('getZoneWith' + keyZone!.name);
      logs.push('get' + keyZone!.get('key'));
      logs.push('root' + Zone.root.name);
      const zonePrototypeKeys = [
        'get',
        'getZoneWith',
        'fork',
        'wrap',
        'run',
        'runGuarded',
        'runTask',
        'scheduleTask',
        'scheduleMicroTask',
        'scheduleMacroTask',
        'scheduleEventTask',
        'cancelTask',
      ];
      zonePrototypeKeys.forEach(key => {
        if ((Zone as any).prototype.hasOwnProperty(key)) {
          logs.push(key);
        }
      });

      const zoneSpecKeys = [
        'name',
        'properties',
        'onFork',
        'onIntercept',
        'onInvoke',
        'onHandleError',
        'onScheduleTask',
        'onInvokeTask',
        'onCancelTask',
        'onHasTask',
      ];
      zoneSpecKeys.forEach(key => {
        if (testZoneSpec.hasOwnProperty(key)) {
          logs.push(key);
        }
      });

      const zoneTaskKeys = [
        'onHasTask', 'runCount', 'type', 'source', 'data', 'scheduleFn', 'cancelFn', 'callback',
        'invoke'
      ];

      const task = Zone.current.scheduleMicroTask('testTask', () => {}, undefined, () => {});
      zoneTaskKeys.forEach(key => {
        if (task.hasOwnProperty(key)) {
          logs.push(key);
        }
      });
    });
  });

  const expectedResult = [
    'currentclosure',
    'parent<root>',
    'getZoneWithclosure',
    'getvalue',
    'root<root>',
    'get',
    'getZoneWith',
    'fork',
    'wrap',
    'run',
    'runGuarded',
    'runTask',
    'scheduleTask',
    'scheduleMicroTask',
    'scheduleMacroTask',
    'scheduleEventTask',
    'cancelTask',
    'name',
    'properties',
    'onFork',
    'onIntercept',
    'onInvoke',
    'onHandleError',
    'onScheduleTask',
    'onInvokeTask',
    'onCancelTask',
    'onHasTask',
    'runCount',
    'type',
    'source',
    'data',
    'scheduleFn',
    'cancelFn',
    'callback',
    'invoke'
  ];

  let result: boolean = true;
  for (let i = 0; i < expectedResult.length; i++) {
    if (expectedResult[i] !== logs[i]) {
      console.log('Not Equals', expectedResult[i], logs[i]);
      result = false;
    }
  }
  if (result) {
    console.log('All tests passed.');
  } else {
    console.error('Test failed, some public APIs cannot be found after closure compiler.');
  }
  process['exit'](result ? 0 : 1);
};
process['on']('uncaughtException', (err: any) => {
  process['exit'](1);
});

testClosureFunction();
