// Copyright 2013 Google Inc. 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.

package com.google.enterprise.adaptor.sharepoint;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;

import com.microsoft.schemas.sharepoint.soap.List;
import com.microsoft.schemas.sharepoint.soap.PolicyUser;
import com.microsoft.schemas.sharepoint.soap.TrueFalseType;
import com.microsoft.schemas.sharepoint.soap.VirtualServer;
import com.microsoft.schemas.sharepoint.soap.Web;

import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * Cache with items that rarely change, so items have a long lifetime in the
 * cache.
 */
class RareModificationCache {
  private final Executor executor;
  private final VirtualServerKey virtualServerKey;
  private final LoadingCache<CacheKey<?>, Object> cache
      = CacheBuilder.newBuilder()
      .expireAfterAccess(5, TimeUnit.MINUTES)
      .expireAfterWrite(30, TimeUnit.MINUTES)
      .build(new AsyncCacheLoader<CacheKey<?>, Object>() {
        @Override
        protected Executor executor() {
          return executor;
        }

        @Override
        public Object load(CacheKey<?> key) throws IOException {
          return key.computeValue();
        }
      });

  public RareModificationCache(SiteDataClient virtualServerSiteDataClient,
      Executor executor) {
    if (virtualServerSiteDataClient == null || executor == null) {
      throw new NullPointerException();
    }
    this.executor = executor;
    this.virtualServerKey = new VirtualServerKey(virtualServerSiteDataClient);
  }

  /**
   * Getter that handles type-safety, and expected to be used for all retrievals
   * from the cache.
   */
  @VisibleForTesting
  <T> T get(CacheKey<T> key) throws IOException {
    try {
      @SuppressWarnings("unchecked")
      T t = (T) cache.get(key);
      return t;
    } catch (ExecutionException e) {
      throw new IOException(e);
    }
  }

  public CachedVirtualServer getVirtualServer() throws IOException {
    return get(virtualServerKey);
  }

  public CachedWeb getWeb(SiteDataClient siteDataClient) throws IOException {
    return get(new WebKey(siteDataClient));
  }

  public CachedList getList(SiteDataClient siteDataClient, String listId)
      throws IOException {
    return get(new ListKey(siteDataClient, listId));
  }

  /**
   * The key used to identify a cache entry. Therefore, {@link Object#equals}
   * and {@link Object#hashCode} must be valid.
   */
  @VisibleForTesting
  interface CacheKey<V> {
    public V computeValue() throws IOException;
  }

  /**
   * Key for the Virtual Server, of which there is only one instance. Therefore,
   * it does not need to override equals and hashCode.
   */
  @VisibleForTesting
  static final class VirtualServerKey implements CacheKey<CachedVirtualServer> {
    private final SiteDataClient siteDataClient;

    public VirtualServerKey(SiteDataClient siteDataClient) {
      this.siteDataClient = siteDataClient;
    }

    @Override
    public CachedVirtualServer computeValue() throws IOException {
      return new CachedVirtualServer(siteDataClient.getContentVirtualServer());
    }
  }

  public static final class CachedVirtualServer {
    public final long anonymousDenyMask;
    public final boolean policyContainsDeny;

    private CachedVirtualServer(VirtualServer vs) {
      this.anonymousDenyMask
          = vs.getPolicies().getAnonymousDenyMask().longValue();
      boolean policyContainsDeny = false;
      for (PolicyUser policyUser : vs.getPolicies().getPolicyUser()) {
        long deny = policyUser.getDenyMask().longValue();
        // If at least one necessary bit is masked, then deny user.
        if ((SharePointAdaptor.LIST_ITEM_MASK & deny) != 0) {
          policyContainsDeny = true;
          break;
        }
      }
      this.policyContainsDeny = policyContainsDeny;
    }
  }

  @VisibleForTesting
  static final class WebKey implements CacheKey<CachedWeb> {
    private final SiteDataClient siteDataClient;

    public WebKey(SiteDataClient siteDataClient) {
      this.siteDataClient = siteDataClient;
    }

    @Override
    public CachedWeb computeValue() throws IOException {
      return new CachedWeb(siteDataClient.getContentWeb());
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof WebKey)) {
        return false;
      }
      WebKey webKey = (WebKey) o;
      return siteDataClient.equals(webKey.siteDataClient);
    }

    @Override
    public int hashCode() {
      return siteDataClient.hashCode();
    }
  }

  public static final class CachedWeb {
    public final String noIndex;
    public final TrueFalseType allowAnonymousAccess;
    public final TrueFalseType anonymousViewListItems;
    public final long anonymousPermMask;
    public final String webTitle;

    public CachedWeb(Web w) {
      this.noIndex = w.getMetadata().getNoIndex();
      this.allowAnonymousAccess = w.getMetadata().getAllowAnonymousAccess();
      this.anonymousViewListItems = w.getMetadata().getAnonymousViewListItems();
      this.anonymousPermMask
          = w.getMetadata().getAnonymousPermMask().longValue();
      this.webTitle = w.getMetadata().getTitle();
    }
  }

  @VisibleForTesting
  static final class ListKey implements CacheKey<CachedList> {
    private final SiteDataClient siteDataClient;
    private final String listId;

    public ListKey(SiteDataClient siteDataClient, String listId) {
      this.siteDataClient = siteDataClient;
      this.listId = listId.toUpperCase(Locale.ENGLISH);
    }

    @Override
    public CachedList computeValue() throws IOException {
      return new CachedList(siteDataClient.getContentList(listId));
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof ListKey)) {
        return false;
      }
      ListKey listKey = (ListKey) o;
      return siteDataClient.equals(listKey.siteDataClient)
          && listId.equals(listKey.listId);
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(new Object[] {siteDataClient, listId});
    }
  }

  public static final class CachedList {
    public final TrueFalseType noIndex;
    public final int readSecurity;
    public final TrueFalseType allowAnonymousAccess;
    public final TrueFalseType anonymousViewListItems;
    public final long anonymousPermMask;
    public final String rootFolder;
    public final String defaultViewUrl;
    public final String defaultViewItemUrl;
    /**
     * This field must not be used for general ACL inheritance of direct
     * decendants of the list. This is intended only for use when determining
     * whether anonymous access is permitted for list items and attachments.
     */
    public final String scopeId;

    public CachedList(List l) {
      this.noIndex = l.getMetadata().getNoIndex();
      this.readSecurity = l.getMetadata().getReadSecurity();
      this.allowAnonymousAccess = l.getMetadata().getAllowAnonymousAccess();
      this.anonymousViewListItems = l.getMetadata().getAnonymousViewListItems();
      this.anonymousPermMask
          = l.getMetadata().getAnonymousPermMask().longValue();
      this.rootFolder = l.getMetadata().getRootFolder();
      this.defaultViewUrl = l.getMetadata().getDefaultViewUrl();
      this.defaultViewItemUrl = l.getMetadata().getDefaultViewItemUrl();
      this.scopeId = l.getMetadata().getScopeID();
    }
  }
}
