/*
 * Copyright 2010 Google Inc.
 * 
 * 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.web.bindery.requestfactory.shared.impl;

import com.google.web.bindery.autobean.shared.AutoBeanFactory;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.ProxySerializer;
import com.google.web.bindery.requestfactory.shared.ProxyStore;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.RequestTransport;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Base type for generated RF interfaces.
 */
public abstract class AbstractRequestFactory extends IdFactory implements
    RequestFactory {
  private static final int MAX_VERSION_ENTRIES = 10000;

  private EventBus eventBus;

  @SuppressWarnings("serial")
  private final Map<String, String> version = new LinkedHashMap<String, String>(
      16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Entry<String, String> eldest) {
      return size() > MAX_VERSION_ENTRIES;
    }
  };
  private RequestTransport transport;

  public <P extends EntityProxy> Request<P> find(final EntityProxyId<P> proxyId) {
    if (((SimpleEntityProxyId<P>) proxyId).isEphemeral()) {
      throw new IllegalArgumentException("Cannot fetch unpersisted entity");
    }

    AbstractRequestContext context = new AbstractRequestContext(
        AbstractRequestFactory.this, AbstractRequestContext.Dialect.STANDARD) {
      @Override
      protected AutoBeanFactory getAutoBeanFactory() {
        return AbstractRequestFactory.this.getAutoBeanFactory();
      }
    };
    return new AbstractRequest<P>(context) {
      {
        requestContext.addInvocation(this);
      }

      @Override
      protected RequestData makeRequestData() {
        return new RequestData(
            "com.google.web.bindery.requestfactory.shared.impl.FindRequest::find",
            new Object[] {proxyId}, propertyRefs, proxyId.getProxyClass(), null);
      }
    };
  }

  public EventBus getEventBus() {
    return eventBus;
  }

  public String getHistoryToken(Class<? extends EntityProxy> clazz) {
    return getTypeToken(clazz);
  }

  public String getHistoryToken(EntityProxyId<?> proxy) {
    return getHistoryToken((SimpleProxyId<?>) proxy);
  }

  public Class<? extends EntityProxy> getProxyClass(String historyToken) {
    String typeToken = IdUtil.getTypeToken(historyToken);
    if (typeToken != null) {
      return getTypeFromToken(typeToken);
    }
    return getTypeFromToken(historyToken);
  }

  @SuppressWarnings("unchecked")
  public <T extends EntityProxy> EntityProxyId<T> getProxyId(String historyToken) {
    return (EntityProxyId<T>) getBaseProxyId(historyToken);
  }

  public RequestTransport getRequestTransport() {
    return transport;
  }

  public ProxySerializer getSerializer(ProxyStore store) {
    return new ProxySerializerImpl(this, store);
  }

  /**
   * The choice of a default request transport is runtime-specific.
   */
  public abstract void initialize(EventBus eventBus);

  public void initialize(EventBus eventBus, RequestTransport transport) {
    this.eventBus = eventBus;
    this.transport = transport;
  }

  /**
   * Implementations of EntityProxies are provided by an AutoBeanFactory, which
   * is itself a generated type. This method knows about all proxy types used in
   * the RequestFactory interface, which prevents pruning of any proxy type. If
   * the {@link #find(EntityProxyId)} and {@link #getSerializer(ProxyStore)}
   * were provided by {@link AbstractRequestContext}, this method could be
   * removed.
   */
  protected abstract AutoBeanFactory getAutoBeanFactory();

  /**
   * Used by {@link AbstractRequestContext} to quiesce update events for objects
   * that haven't truly changed.
   */
  protected boolean hasVersionChanged(SimpleProxyId<?> id,
      String observedVersion) {
    assert id != null : "id";
    assert observedVersion != null : "observedVersion";
    String key = getHistoryToken(id);
    String existingVersion = version.get(key);
    // Return true if we haven't seen this before or the versions differ
    boolean toReturn = existingVersion == null
        || !existingVersion.equals(observedVersion);
    if (toReturn) {
      version.put(key, observedVersion);
    }
    return toReturn;
  }
}
