/*
 * 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.gwt.requestfactory.server;

import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
import com.google.gwt.requestfactory.shared.ProxyFor;
import com.google.gwt.requestfactory.shared.ProxyForName;
import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.Service;
import com.google.gwt.requestfactory.shared.ServiceLocator;
import com.google.gwt.requestfactory.shared.ServiceName;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * Adds support to the ServiceLayer chain for using {@link Locator} and
 * {@link ServiceLocator} helper objects.
 */
final class LocatorServiceLayer extends ServiceLayerDecorator {

  @Override
  public <T> T createDomainObject(Class<T> clazz) {
    Locator<T, ?> l = getLocator(clazz);
    if (l == null) {
      return super.createDomainObject(clazz);
    }
    return l.create(clazz);
  }

  @Override
  public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
    return newInstance(clazz, Locator.class);
  }

  @Override
  public Object createServiceInstance(Method contextMethod, Method domainMethod) {
    Class<? extends ServiceLocator> locatorType = getTop().resolveServiceLocator(
        contextMethod, domainMethod);
    ServiceLocator locator = newInstance(locatorType, ServiceLocator.class);
    return locator.getInstance(domainMethod.getDeclaringClass());
  }

  @Override
  public Object getId(Object domainObject) {
    return doGetId(domainObject);
  }

  @Override
  public Class<?> getIdType(Class<?> domainType) {
    Locator<?, ?> l = getLocator(domainType);
    if (l == null) {
      return super.getIdType(domainType);
    }
    return l.getIdType();
  }

  @Override
  public Object getVersion(Object domainObject) {
    return doGetVersion(domainObject);
  }

  @Override
  public boolean isLive(Object domainObject) {
    return doIsLive(domainObject);
  }

  @Override
  public <T> T loadDomainObject(Class<T> clazz, Object domainId) {
    return doLoadDomainObject(clazz, domainId);
  }

  /**
   * Returns true if the context method returns a {@link Request} and the domain
   * method is non-static.
   */
  @Override
  public boolean requiresServiceLocator(Method contextMethod,
      Method domainMethod) {
    return Request.class.isAssignableFrom(contextMethod.getReturnType())
        && !Modifier.isStatic(domainMethod.getModifiers());
  }

  @Override
  public Class<? extends Locator<?, ?>> resolveLocator(Class<?> domainType) {
    // Find the matching BaseProxy
    Class<?> proxyType = getTop().resolveClientType(domainType,
        BaseProxy.class, false);
    if (proxyType == null) {
      return null;
    }

    // Check it for annotations
    Class<? extends Locator<?, ?>> locatorType;
    ProxyFor l = proxyType.getAnnotation(ProxyFor.class);
    ProxyForName ln = proxyType.getAnnotation(ProxyForName.class);
    if (l != null && !Locator.class.equals(l.locator())) {
      @SuppressWarnings("unchecked")
      Class<? extends Locator<?, ?>> found = (Class<? extends Locator<?, ?>>) l.locator();
      locatorType = found;
    } else if (ln != null && ln.locator().length() > 0) {
      try {
        @SuppressWarnings("unchecked")
        Class<? extends Locator<?, ?>> found = (Class<? extends Locator<?, ?>>) Class.forName(
            ln.locator(), false, domainType.getClassLoader()).asSubclass(
            Locator.class);
        locatorType = found;
      } catch (ClassNotFoundException e) {
        return die(
            e,
            "Could not find the locator type specified in the @%s annotation %s",
            ProxyForName.class.getCanonicalName(), ln.value());
      }
    } else {
      // No locator annotation
      locatorType = null;
    }
    return locatorType;
  }

  @Override
  public Class<? extends ServiceLocator> resolveServiceLocator(
      Method contextMethod, Method domainMethod) {
    Class<? extends ServiceLocator> locatorType;

    // Look at the RequestContext
    Class<?> requestContextClass = contextMethod.getDeclaringClass();
    Service l = requestContextClass.getAnnotation(Service.class);
    ServiceName ln = requestContextClass.getAnnotation(ServiceName.class);
    if (l != null && !ServiceLocator.class.equals(l.locator())) {
      locatorType = l.locator();
    } else if (ln != null && ln.locator().length() > 0) {
      try {
        locatorType = Class.forName(ln.locator(), false,
            requestContextClass.getClassLoader()).asSubclass(
            ServiceLocator.class);
      } catch (ClassNotFoundException e) {
        return die(
            e,
            "Could not find the locator type specified in the @%s annotation %s",
            ServiceName.class.getCanonicalName(), ln.value());
      }
    } else {
      locatorType = null;
    }
    return locatorType;
  }

  private <T> Object doGetId(T domainObject) {
    @SuppressWarnings("unchecked")
    Class<T> clazz = (Class<T>) domainObject.getClass();
    Locator<T, ?> l = getLocator(clazz);
    if (l == null) {
      return super.getId(domainObject);
    }
    return l.getId(domainObject);
  }

  private <T> Object doGetVersion(T domainObject) {
    @SuppressWarnings("unchecked")
    Class<T> clazz = (Class<T>) domainObject.getClass();
    Locator<T, ?> l = getLocator(clazz);
    if (l == null) {
      return super.getVersion(domainObject);
    }
    return l.getVersion(domainObject);
  }

  private <T> boolean doIsLive(T domainObject) {
    @SuppressWarnings("unchecked")
    Class<T> clazz = (Class<T>) domainObject.getClass();
    Locator<T, ?> l = getLocator(clazz);
    if (l == null) {
      return super.isLive(domainObject);
    }
    return l.isLive(domainObject);
  }

  private <T, I> T doLoadDomainObject(Class<T> clazz, Object domainId) {
    @SuppressWarnings("unchecked")
    Locator<T, I> l = (Locator<T, I>) getLocator(clazz);
    if (l == null) {
      return super.loadDomainObject(clazz, domainId);
    }
    I id = l.getIdType().cast(domainId);
    return l.find(clazz, id);
  }

  @SuppressWarnings("unchecked")
  private <T, I> Locator<T, I> getLocator(Class<T> domainType) {
    Class<? extends Locator<?, ?>> locatorType = getTop().resolveLocator(
        domainType);
    if (locatorType == null) {
      return null;
    }
    return (Locator<T, I>) getTop().createLocator(locatorType);
  }

  private <T> T newInstance(Class<T> clazz, Class<? super T> base) {
    Throwable ex;
    try {
      return clazz.newInstance();
    } catch (InstantiationException e) {
      ex = e;
    } catch (IllegalAccessException e) {
      ex = e;
    }
    return this.<T> die(ex,
        "Could not instantiate %s %s. Is it default-instantiable?",
        base.getSimpleName(), clazz.getCanonicalName());
  }
}
