<!--
This is a light weighted demo page used to Pre-app Recommendation Service.
Start a http server by running this python3 command:
python3 -m http.server 8000
Then navigate to Cobalt binary directory, run in Cobalt using this command:
./cobalt --url=http://localhost:8000/cobalt/demos/content/pre-app-recommendation-demo/pre-app-recommendation-demo.html
-->
<!DOCTYPE html>
<meta charset="utf-8">

<body>
  <script>
    'use strict';
    /**
    * @param {ArrayBuffer} data to be converted to a String.
    */
    function ab2str(data) {
      try {
        return String.fromCharCode.apply(null, new Uint8Array(data));
      } catch (error) {
        console.error(`ab2str() error: ${error}, decoding data: ${data}`);
      }
    }

    /**
    * @param {String} data to be converted to an ArrayBuffer.
    */
    function str2ab(data) {
      try {
        return Uint8Array.from(data.split(''), (s) => { return s.charCodeAt(0) }).buffer;
      } catch (error) {
        console.error(`str2ab() error: ${error}, decoding data: ${data}`);
      }
    }

    async function testPreappRecommendationService() {

      if (!H5vccPlatformService) {
        // H5vccPlatformService is not implemented.
        console.error("H5vccPlatformService is not implemented");
        return;
      }

      var RECS_SERVICE_NAME = "com.google.youtube.tv.Recommendations";

      if (!H5vccPlatformService.has(RECS_SERVICE_NAME)) {
        // RECS_SERVICE_NAME is not implemented.
        console.error(`H5vccPlatformService.Has(${RECS_SERVICE_NAME}) returned false.`);
        return;
      }

      /**
      * @param {ArrayBuffer} data
      */
      function receiveCallback(service, data) {

        var str_response = ab2str(data);
        console.error(`receiveCallback() receives str_response: ${str_response} but receiveCallback() isn't supported today`);

      }

      // Open the pre app recommendation service.
      var pre_app_recommendation_service = H5vccPlatformService.open(RECS_SERVICE_NAME,
        receiveCallback);

      // Send method getPartnerId and receive platform response.
      var get_partner_id_response = pre_app_recommendation_service.send(str2ab(JSON.stringify({ 'method': 'getPartnerId' })));

      try {
        var partner_id = ab2str(get_partner_id_response);
        console.log(`send() method getPartnerId platform response : ${partner_id}`);
      } catch (error) {
        console.error(`Error in parsing response from platform for method getPartnerId: ${error}`);
        return;
      }

      // Send method recommend, upsert operation and recs_response.
      // recs_response will follow the response format in https://developers.google.com/youtube/recommendations/reference/rest/v1/ListRecommendationsResponse
      var upsert_operation = str2ab(JSON.stringify({
        'method': 'recommend',
        'operation': 'upsert',
        'recs_response': {
          'shelves': [{
            'title': 'top picks for you',
            'shelf_items': [{
              'title': '25 Best Countries to visit',
              'url': 'https://www.youtube.com/tv?v=HcdohhNq8Iw&&launch=launcher',
              'images': [{
                'uri': 'https://i.ytimg.com/vi/HcdohhNq8Iw/default.jpg',
                'width': '120',
                'height': '90',
                'resolution': 'DEFAULT_RESOLUTION'
              }]
            }]
          }
          ]
        }
      }));

      var delete_operation = str2ab(JSON.stringify({
        'method': 'recommend', 'operation': 'delete'
      }));

      for (let data of [upsert_operation, delete_operation]) {
        var recommend_response = ab2str(pre_app_recommendation_service.send(data));
        try {
          console.log(`send() method recommend platform response: ${recommend_response}`);
        } catch (error) {
          console.error(`Error in parsing response from platform for method recommend: ${error}`);
        }
      }

      // Close the service after a timeout. This is in case there is an error on
      // the platform and a response is not received in the receiveCallback().
      var TIME_BEFORE_CLOSE = 10000;
      await new Promise(r => setTimeout(r, TIME_BEFORE_CLOSE));
      pre_app_recommendation_service.close();
    }

    window.onload = () => {
      testPreappRecommendationService();
    }

  </script>
</body>
