/*
 * 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.client.impl;

import com.google.gwt.autobean.shared.AutoBean;
import com.google.gwt.autobean.shared.AutoBeanUtils;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorContext;
import com.google.gwt.editor.client.EditorVisitor;
import com.google.gwt.editor.client.impl.AbstractEditorDelegate;
import com.google.gwt.editor.client.impl.BaseEditorDriver;
import com.google.gwt.editor.client.impl.DelegateMap;
import com.google.gwt.editor.client.impl.DelegateMap.KeyMethod;
import com.google.gwt.editor.client.impl.SimpleViolation;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.requestfactory.client.HasRequestContext;
import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.ValueProxy;
import com.google.gwt.requestfactory.shared.Violation;
import com.google.gwt.requestfactory.shared.impl.Constants;

import java.util.Iterator;
import java.util.List;

/**
 * Contains utility methods for top-level driver implementations.
 *
 * <p><span style='color:red'>RequestFactory has moved to
 * <code>com.google.web.bindery.requestfactory</code>.  This package will be
 * removed in a future version of GWT.</span></p>
 *
 * @param <R> the type being edited
 * @param <E> the type of Editor
 */
@Deprecated
public abstract class AbstractRequestFactoryEditorDriver<R, E extends Editor<R>>
    extends BaseEditorDriver<R, E> implements RequestFactoryEditorDriver<R, E> {

  /**
   * Adapts a RequestFactory Violation object to the SimpleViolation interface.
   *
   * <p><span style='color:red'>RequestFactory has moved to
   * <code>com.google.web.bindery.requestfactory</code>.  This package will be
   * removed in a future version of GWT.</span></p>
   */
  @Deprecated
  static class SimpleViolationAdapter extends SimpleViolation {
    private final Violation v;

    /**
     * @param source
     */
    private SimpleViolationAdapter(Violation v) {
      this.v = v;
    }

    public Object getKey() {
      return v.getOriginalProxy();
    }

    public String getMessage() {
      return v.getMessage();
    }

    public String getPath() {
      return v.getPath();
    }

    public Object getUserDataObject() {
      return v;
    }
  }
  /**
   * Provides a source of SimpleViolation objects based on RequestFactory's
   * simplified Violation interface.
   *
   * <p><span style='color:red'>RequestFactory has moved to
   * <code>com.google.web.bindery.requestfactory</code>.  This package will be
   * removed in a future version of GWT.</span></p>
   */
  @Deprecated
  static class ViolationIterable implements Iterable<SimpleViolation> {

    private final Iterable<Violation> violations;

    public ViolationIterable(Iterable<Violation> violations) {
      this.violations = violations;
    }

    public Iterator<SimpleViolation> iterator() {
      final Iterator<Violation> source = violations.iterator();
      return new Iterator<SimpleViolation>() {
        public boolean hasNext() {
          return source.hasNext();
        }

        public SimpleViolation next() {
          return new SimpleViolationAdapter(source.next());
        }

        public void remove() {
          source.remove();
        }
      };
    }
  }

  /**
   * Since the ValueProxy is being mutated in-place, we need a way to stabilize
   * its hashcode for future equality checks.
   */
  private static class ValueProxyHolder {
    private final ValueProxy proxy;

    public ValueProxyHolder(ValueProxy proxy) {
      this.proxy = proxy;
    }

    @Override
    public boolean equals(Object o) {
      return proxy.equals(((ValueProxyHolder) o).proxy);
    }

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

  private static final DelegateMap.KeyMethod PROXY_ID_KEY = new DelegateMap.KeyMethod() {
    public Object key(Object object) {
      if (object instanceof EntityProxy) {
        return ((EntityProxy) object).stableId();
      } else if (object instanceof ValueProxy) {
        AutoBean<?> bean = AutoBeanUtils.getAutoBean(object);
        // Possibly replace an editable ValueProxy with its immutable base
        AutoBean<?> parent = bean.getTag(Constants.PARENT_OBJECT);
        if (parent != null) {
          object = parent.as();
        }
        return new ValueProxyHolder((ValueProxy) object);
      }
      return null;
    }
  };

  private EventBus eventBus;
  private List<String> paths;
  private RequestFactory factory;
  private RequestContext saveRequest;

  public void display(R object) {
    edit(object, null);
  }

  public void edit(R object, final RequestContext saveRequest) {
    this.saveRequest = saveRequest;
    // Provide the delegate and maybe the editor with the RequestContext
    accept(new EditorVisitor() {
      @Override
      public <T> void endVisit(EditorContext<T> ctx) {
        RequestFactoryEditorDelegate<?, ?> delegate = (RequestFactoryEditorDelegate<?, ?>) ctx.getEditorDelegate();
        if (delegate != null) {
          delegate.setRequestContext(saveRequest);
        }
        Editor<T> editor = ctx.getEditor();
        if (editor instanceof HasRequestContext) {
          ((HasRequestContext<T>) editor).setRequestContext(saveRequest);
        }
      }
    });
    doEdit(object);
  }

  public RequestContext flush() {
    checkSaveRequest();
    doFlush();
    return saveRequest;
  }

  public String[] getPaths() {
    return paths.toArray(new String[paths.size()]);
  }

  public void initialize(E editor) {
    doInitialize(null, null, editor);
  }

  public void initialize(EventBus eventBus, RequestFactory requestFactory,
      E editor) {
    assert eventBus != null : "eventBus must not be null";
    assert requestFactory != null : "requestFactory must not be null";
    doInitialize(eventBus, requestFactory, editor);
  }

  public void initialize(RequestFactory requestFactory, E editor) {
    initialize(requestFactory.getEventBus(), requestFactory, editor);
  }

  public boolean setViolations(Iterable<Violation> violations) {
    return doSetViolations(new ViolationIterable(violations));
  }

  protected void checkSaveRequest() {
    if (saveRequest == null) {
      throw new IllegalStateException("edit() was called with a null Request");
    }
  }

  @Override
  protected void configureDelegate(AbstractEditorDelegate<R, E> rootDelegate) {
    ((RequestFactoryEditorDelegate<R, E>) rootDelegate).initialize(eventBus,
        factory, "", getEditor());
  }

  protected void doInitialize(EventBus eventBus, RequestFactory requestFactory,
      E editor) {
    this.eventBus = eventBus;
    this.factory = requestFactory;
    super.doInitialize(editor);
    PathCollector c = new PathCollector();
    accept(c);
    this.paths = c.getPaths();
  }

  @Override
  protected KeyMethod getViolationKeyMethod() {
    return PROXY_ID_KEY;
  }
}
