/**
 * This file is part of the Meeds project (https://meeds.io/).
 *
 * Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package org.exoplatform.social.core.storage.cache.selector;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;

import org.exoplatform.services.cache.ExoCache;
import org.exoplatform.services.cache.ObjectCacheInfo;
import org.exoplatform.social.core.space.model.Space;
import org.exoplatform.social.core.storage.cache.SocialStorageCacheService;
import org.exoplatform.social.core.storage.cache.model.data.ListSpacesData;
import org.exoplatform.social.core.storage.cache.model.key.ListSpacesKey;
import org.exoplatform.social.core.storage.cache.model.key.SpaceFilterKey;
import org.exoplatform.social.core.storage.cache.model.key.SpaceKey;
import org.exoplatform.social.core.storage.cache.model.key.SpaceType;

/**
 * Cache selector for last accessed spaces. It select all cache entries for the
 * given userId and for space type LATEST_ACCESSED or VISITED.
 */
public class LastAccessedSpacesCacheSelector extends CacheSelector<ListSpacesKey, ListSpacesData> {

  private String                    remoteId;

  private long                      templateId;

  private Space                     space;

  private SocialStorageCacheService cacheService;

  private boolean                   updateStore = true;

  public LastAccessedSpacesCacheSelector(String remoteId, Space space, SocialStorageCacheService cacheService) {
    this.remoteId = remoteId;
    this.space = space;
    this.cacheService = cacheService;
  }

  @Override
  public boolean select(ListSpacesKey listSpacesKey, ObjectCacheInfo<? extends ListSpacesData> objectCacheInfo) {
    if (listSpacesKey == null || listSpacesKey.getKey() == null) {
      return false;
    } else {
      SpaceFilterKey spaceFilterKey = listSpacesKey.getKey();
      return remoteId.equals(spaceFilterKey.getUserId())
             && SpaceType.LATEST_ACCESSED.equals(spaceFilterKey.getType());
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public void onSelect(ExoCache<? extends ListSpacesKey, ? extends ListSpacesData> exoCache,
                       ListSpacesKey listSpacesKey,
                       ObjectCacheInfo<? extends ListSpacesData> objectCacheInfo) throws Exception {
    if (objectCacheInfo != null && objectCacheInfo.get() != null) {
      ListSpacesData listSpacesData = objectCacheInfo.get();
      List<SpaceKey> ids = listSpacesData.getIds();
      if (ids != null && !ids.isEmpty()) {
        if (ids.get(0).getId() == space.getSpaceId()) {
          updateStore = false;
          return;
        } else if (listSpacesKey.getOffset() == 0
                   && SpaceType.LATEST_ACCESSED.equals(listSpacesKey.getKey().getType())
                   && (CollectionUtils.size(listSpacesKey.getKey().getTemplateIds()) != 1
                       || templateId == listSpacesKey.getKey().getTemplateIds().get(0))) {
          SpaceKey spaceKey = new SpaceKey(space.getSpaceId());
          ids = new ArrayList<>(ids);
          if (ids.contains(spaceKey)) {
            ids.remove(spaceKey);
            ids.add(0, spaceKey);
            listSpacesData.setIds(ids);
            // Update cache after value change because ISPN returns a clone of
            // object And not the real cached object
            ((ExoCache<ListSpacesKey, ListSpacesData>) exoCache).put(listSpacesKey, listSpacesData);
            // Cache enry updated, so no need to clear it
            return;
          }
        }
      }
      exoCache.remove(listSpacesKey);
      cacheService.getSpacesCountCache().remove(listSpacesKey);
    }
  }

  public boolean isUpdateStore() {
    return updateStore;
  }
}
