<!--
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-default-expanded="{ props.catalogDefaultExpanded || state.nRepositories === 1 }"
    z-index="{ props.catalogMaxBranches - props.catalogMinBranches + 2 }"
    is-registry-secured="{ props.isRegistrySecured }"
  ></catalog-element>
  <script>
    import CatalogElement from './catalog-element.riot';
    import { Http } from '../../scripts/http';
    import { getBranching } from '../../scripts/repositories';
    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;
        try {
          this.state.branching = getBranching(props.catalogMinBranches, props.catalogMaxBranches);
        } catch (e) {
          props.onNotify(e);
        }
      },
      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 = [];
        let nImages = 0;
        const self = this;
        const catalogUrl = `${props.registryUrl}/v2/_catalog?n=${state.catalogElementsLimit}`;
        const oReq = new Http({
          onAuthentication: this.props.onAuthentication,
          withCredentials: props.isRegistrySecured,
        });
        oReq.addEventListener('load', function () {
          if (this.status === 200) {
            repositories = JSON.parse(this.responseText).repositories || [];
            repositories.sort();
            nImages = repositories.length;
            if (typeof state.branching === 'function') {
              repositories = state.branching(repositories);
            }
          } else if (this.status === 404) {
            self.props.onNotify({ code: 'CATALOG_NOT_FOUND', url: catalogUrl }, true);
          } else if (this.status === 400) {
            let response;
            try {
              response = JSON.parse(this.responseText);
            } catch (e) {}
            if (!response || !Array.isArray(response.errors)) {
              return self.props.onNotify(this.responseText, true);
            }
            self.props.onNotify({ ...response, 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,
            loadend: true,
          });
        });
        oReq.open('GET', catalogUrl);
        oReq.send();
      },
    };
  </script>
  <style>
    catalog {
      display: block;
      margin: auto;
    }
    catalog > material-card {
      width: 100%;
    }
  </style>
</catalog>
