<!DOCTYPE html>
<!--
  Copyright 2022 The Cobalt Authors. 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.
-->
<!--
  This is a basic test of the message event for service workers.
-->

<html>

<head>
    <title>Cobalt Service Worker Message Test</title>
    <script src='black_box_js_test_utils.js'></script>
</head>

<body>
    <script>
        h5vcc.storage.clearServiceWorkerCache();

        var expected_event_count = 0;

        function count_event(expected_value) {
            expected_event_count += 1;
            console.log('Expected events counted:', expected_event_count)
            if (expected_value) {
                assertEqual(expected_value, expected_event_count)
            }
            return expected_event_count;
        }

        navigator.serviceWorker.onmessage = function (event) {
            console.log('Got onmessage event ', JSON.stringify(event.data));;
            assertTrue(event instanceof MessageEvent);
            assertEqual('[object MessageEvent]', `${event}`);
            assertEqual('[object ServiceWorkerContainer]', `${event.target}`);
            assertEqual('[object Object]', `${event.data}`);
            switch (count_event()) {
                case 3:
                    assertEqual('Foo', event.data.text);
                    assertEqual('BarString', event.data.bar);
                    break;
                case 4:
                    assertEqual('Service Worker received a message from source',
                        event.data.text);
                    assertEqual('{"message":"Registration ready resolved."}',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                case 5:
                    assertEqual('Service Worker received a message from client',
                        event.data.text);
                    assertEqual('{"message":"Registration ready resolved."}',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                case 6:
                    assertEqual('Foo', event.data.text);
                    assertEqual('BarString', event.data.bar);
                    break;
                case 7:
                    assertEqual('Service Worker received a message from source',
                        event.data.text);
                    assertEqual('"Controllerchange event received."',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                case 8:
                    assertEqual('Service Worker received a message from client',
                        event.data.text);
                    assertEqual('"Controllerchange event received."',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                default:
                    notReached();
                    break;
            }

        }

        navigator.serviceWorker.oncontrollerchange = function (event) {
            console.log('Got oncontrollerchange event', event.target);
            count_event(2);
            navigator.serviceWorker.controller.postMessage(
                'Controllerchange event received.');
        }

        navigator.serviceWorker.ready.then(function (
            registration) {
            assertNotEqual(null, registration);
            assertNotEqual(null, registration.active);
            registration.active.postMessage({ message:
                'Registration ready resolved.'});
            count_event(1);
            window.setTimeout(
                () => {
                    registration.unregister()
                        .then(function (success) {
                            console.log('(Expected) unregister success :',
                                success);
                            count_event(9);
                        }, function (error) {
                            console.log('(Unexpected) unregister ' +
                                `${error}`, error);
                            assertIncludes('SecurityError: ', `${error}`);
                            notReached();
                        });
                }, 1000);
        });

        navigator.serviceWorker.register('service_worker_message_test.js', {
            scope: './',
        }).catch(function (error) {
            console.log('(Unexpected) :', error);
            notReached();
        });

        setupFinished();
        // This delay has to be long enough to guarantee that the test has
        // finished.
        window.setTimeout(
            () => {
                console.log('Events:', expected_event_count)
                assertEqual(9, expected_event_count);
                onEndTest();
            }, 2000);

    </script>
</body>

</html>
