/* @license
 * Copyright 2019 Google LLC. All Rights Reserved.
 * 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.
 */

import {IS_IOS} from '../../constants.js';
import {ARInterface, ARMixin, openSceneViewer} from '../../features/ar.js';
import ModelViewerElementBase from '../../model-viewer-base.js';
import {Constructor} from '../../utilities.js';
import {assetPath, spy, timePasses, waitForEvent} from '../helpers.js';
import {BasicSpecTemplate} from '../templates.js';

const expect = chai.expect;

suite('ModelViewerElementBase with ARMixin', () => {
  suite('when registered', () => {
    let nextId = 0;
    let tagName: string;
    let ModelViewerElement: Constructor<ModelViewerElementBase&ARInterface>;

    setup(() => {
      tagName = `model-viewer-ar-${nextId++}`;
      ModelViewerElement = class extends ARMixin
      (ModelViewerElementBase) {
        static get is() {
          return tagName;
        }
      };
      customElements.define(tagName, ModelViewerElement);
    });

    BasicSpecTemplate(() => ModelViewerElement, () => tagName);

    suite('openSceneViewer', () => {
      test('preserves query parameters in model URLs', () => {
        const intentUrls: Array<string> = [];
        const restoreAnchorClick = spy(HTMLAnchorElement.prototype, 'click', {
          value: function() {
            intentUrls.push((this as HTMLAnchorElement).href);
          }
        });

        openSceneViewer(
            'https://example.com/model.gltf?token=foo', 'Example model');

        expect(intentUrls.length).to.be.equal(1);

        const url = new URL(intentUrls[0]);

        expect(url.search).to.match(/[\?&]token=foo(&|$)/);

        restoreAnchorClick();
      });
    });

    suite('quick-look-browsers', () => {
      // TODO(#624,#625): We cannot implement these tests without the ability
      // to mock our constants
      test('shows the AR button for allowed browsers');
      test('hides the AR button for non-allowed browsers');
    });

    suite('with unstable-webxr', () => {
      let element: ModelViewerElementBase&ARInterface;

      setup(async () => {
        element = new ModelViewerElement();
        document.body.appendChild(element);

        element.unstableWebxr = true;
        element.src = assetPath('Astronaut.glb');

        await waitForEvent(element, 'load');
      });

      teardown(() => {
        if (element.parentNode != null) {
          element.parentNode.removeChild(element);
        }
      });

      test('hides the AR button if not on AR platform', () => {
        expect(element.canActivateAR).to.be.equal(false);
      });

      test('shows the AR button if on AR platform');
    });

    suite('ios-src', () => {
      let element: ModelViewerElementBase&ARInterface;

      setup(async () => {
        element = new ModelViewerElement();
        document.body.appendChild(element);

        element.src = assetPath('Astronaut.glb');

        await waitForEvent(element, 'load');
      });

      teardown(() => {
        if (element.parentNode != null) {
          element.parentNode.removeChild(element);
        }
      });

      if (IS_IOS) {
        suite('on iOS Safari', () => {
          test('hides the AR button', () => {
            expect(element.canActivateAR).to.be.equal(false);
          });

          suite('with an ios-src', () => {
            setup(async () => {
              element.iosSrc = assetPath('Astronaut.usdz');
              await timePasses();
            });

            test('shows the AR button', () => {
              expect(element.canActivateAR).to.be.equal(true);
            });
          });
        });
      } else {
        suite('on browsers that are not iOS Safari', () => {
          test('hides the AR button', () => {
            expect(element.canActivateAR).to.be.equal(false);
          });

          suite('with an ios-src', () => {
            setup(async () => {
              element.iosSrc = assetPath('Astronaut.usdz');
              await timePasses();
            });

            test('still hides the AR button', () => {
              expect(element.canActivateAR).to.be.equal(false);
            });
          });
        });
      }
    });
  });
});
