<!--
Copyright (C) 2016-2023 Jones Magloire @Joxit

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<catalog>
  <material-card ref="catalog-tag" class="catalog header">
    <div class="material-card-title-action">
      <h2>
        Repositories of { state.registryName }
        <div class="item-count">{ state.nImages } images in { state.nRepositories } repositories</div>
      </h2>
    </div>
  </material-card>
  <div if="{ !state.loadend }" class="spinner-wrapper">
    <material-spinner></material-spinner>
  </div>
  <catalog-element
    each="{ item in state.repositories }"
    item="{ item }"
    filter-results="{ props.filterResults }"
    registry-url="{ props.registryUrl }"
    on-notify="{ props.onNotify }"
    on-authentication="{ props.onAuthentication }"
    show-catalog-nb-tags="{ props.showCatalogNbTags }"
  ></catalog-element>
  <script>
    import CatalogElement from './catalog-element.riot';
    import { Http } from '../../scripts/http';
    import { getRegistryServers } from '../../scripts/utils';

    export default {
      components: {
        CatalogElement,
      },
      state: {
        registryName: '',
        length: 0,
        loadend: false,
        repositories: [],
        registryUrl: '',
      },

      onBeforeMount(props) {
        this.state.registryName = props.registryName;
        this.state.catalogElementsLimit = props.catalogElementsLimit;
      },
      onMounted(props, state) {
        this.display(props, state);
      },
      onUpdated(props, state) {
        this.display(props, state);
      },
      display(props, state) {
        if (props.registryUrl === state.registryUrl) {
          return;
        }
        state.registryUrl = props.registryUrl;
        let repositories = [];
        const self = this;
        const catalogUrl = `${props.registryUrl}/v2/_catalog?n=${state.catalogElementsLimit}`;
        const oReq = new Http({
          onAuthentication: this.props.onAuthentication,
        });
        oReq.addEventListener('load', function () {
          if (this.status === 200) {
            repositories = JSON.parse(this.responseText).repositories || [];
            repositories.sort();
            repositories = repositories.reduce(function (acc, e) {
              const slash = e.indexOf('/');
              if (slash > 0) {
                const repoName = e.substring(0, slash) + '/';
                if (acc.length === 0 || acc[acc.length - 1].repo != repoName) {
                  acc.push({
                    repo: repoName,
                    images: [],
                  });
                }
                acc[acc.length - 1].images.push(e);
                return acc;
              }
              acc.push(e);
              return acc;
            }, []);
          } else if (this.status === 404) {
            self.props.onNotify({ code: 'CATALOG_NOT_FOUND', url: catalogUrl }, true);
          } else {
            self.props.onNotify(this.responseText);
          }
        });
        oReq.addEventListener('error', function () {
          self.props.onNotify(this.getErrorMessage(), true);
        });
        oReq.addEventListener('loadend', function () {
          self.update({
            repositories,
            nRepositories: repositories.length,
            nImages: repositories.reduce((acc, e) => acc + ((e.images && e.images.length) || 1), 0),
            loadend: true,
          });
        });
        oReq.open('GET', catalogUrl);
        oReq.send();
      },
    };
  </script>
</catalog>
