/*
 * 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.RequestContext;
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);
    // Enclosing class may be a parent class, so invoke on service class
    Class<?> declaringClass = contextMethod.getDeclaringClass();
    Class<?> serviceClass =
        getTop().resolveServiceClass((Class<? extends RequestContext>) declaringClass);
    return locator.getInstance(serviceClass);
  }

  @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,
                getTop().getDomainClassLoader()).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, getTop().getDomainClassLoader()).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());
  }
}
