// Copyright (C) 2013 The Android Open Source Project
//
// 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.gerrit.client.projects;

import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import java.util.LinkedHashMap;
import java.util.Map;

/** Cache of {@link ConfigInfo} objects by project name. */
public class ConfigInfoCache {
  private static final int PROJECT_LIMIT = 25;
  private static final int CHANGE_LIMIT = 100;
  private static final ConfigInfoCache instance = GWT.create(ConfigInfoCache.class);

  public static class Entry {
    private final ConfigInfo info;
    private CommentLinkProcessor commentLinkProcessor;

    private Entry(ConfigInfo info) {
      this.info = info;
    }

    public CommentLinkProcessor getCommentLinkProcessor() {
      if (commentLinkProcessor == null) {
        commentLinkProcessor = new CommentLinkProcessor(info.commentlinks());
      }
      return commentLinkProcessor;
    }

    public ThemeInfo getTheme() {
      return info.theme();
    }
  }

  public static void get(Project.NameKey name, AsyncCallback<Entry> cb) {
    instance.getImpl(name.get(), cb);
  }

  public static void get(Change.Id changeId, AsyncCallback<Entry> cb) {
    instance.getImpl(changeId.get(), cb);
  }

  public static void add(ChangeInfo info) {
    instance.changeToProject.put(info.legacyId().get(), info.project());
  }

  private final LinkedHashMap<String, Entry> cache;
  private final LinkedHashMap<Integer, String> changeToProject;

  protected ConfigInfoCache() {
    cache =
        new LinkedHashMap<String, Entry>(PROJECT_LIMIT) {
          private static final long serialVersionUID = 1L;

          @Override
          protected boolean removeEldestEntry(Map.Entry<String, ConfigInfoCache.Entry> e) {
            return size() > PROJECT_LIMIT;
          }
        };

    changeToProject =
        new LinkedHashMap<Integer, String>(CHANGE_LIMIT) {
          private static final long serialVersionUID = 1L;

          @Override
          protected boolean removeEldestEntry(Map.Entry<Integer, String> e) {
            return size() > CHANGE_LIMIT;
          }
        };
  }

  private void getImpl(final String name, final AsyncCallback<Entry> cb) {
    Entry e = cache.get(name);
    if (e != null) {
      cb.onSuccess(e);
      return;
    }
    ProjectApi.getConfig(
        new Project.NameKey(name),
        new AsyncCallback<ConfigInfo>() {
          @Override
          public void onSuccess(ConfigInfo result) {
            Entry e = new Entry(result);
            cache.put(name, e);
            cb.onSuccess(e);
          }

          @Override
          public void onFailure(Throwable caught) {
            cb.onFailure(caught);
          }
        });
  }

  private void getImpl(final Integer id, final AsyncCallback<Entry> cb) {
    String name = changeToProject.get(id);
    if (name != null) {
      getImpl(name, cb);
      return;
    }
    ChangeApi.change(id)
        .get(
            new AsyncCallback<ChangeInfo>() {
              @Override
              public void onSuccess(ChangeInfo result) {
                changeToProject.put(id, result.project());
                getImpl(result.project(), cb);
              }

              @Override
              public void onFailure(Throwable caught) {
                cb.onFailure(caught);
              }
            });
  }
}
