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

import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorDriver;
import com.google.gwt.editor.client.impl.DelegateMap.KeyMethod;

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

import javax.validation.ConstraintViolation;

/**
 * Abstraction of a ConstraintViolation or a RequestFactory Violation object.
 * Also contains a factory method to create SimpleViolation instances from
 * {@link ConstraintViolation} objects.
 */
public abstract class SimpleViolation {
  /**
   * Provides a source of SimpleViolation objects based on ConstraintViolations.
   * This is re-used by the RequestFactoryEditorDriver implementation, which
   * does not share a type hierarchy with the SimpleBeanEditorDriver.
   */
  static class ConstraintViolationIterable implements Iterable<SimpleViolation> {

    private final Iterable<ConstraintViolation<?>> violations;

    public ConstraintViolationIterable(
        Iterable<ConstraintViolation<?>> violations) {
      this.violations = violations;
    }

    public Iterator<SimpleViolation> iterator() {
      // Use a fresh source iterator each time
      final Iterator<ConstraintViolation<?>> 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();
        }
      };
    }
  }

  /**
   * Adapts the ConstraintViolation interface to the SimpleViolation interface.
   */
  static class SimpleViolationAdapter extends SimpleViolation {
    private final ConstraintViolation<?> v;

    public SimpleViolationAdapter(ConstraintViolation<?> v) {
      this.v = v;
    }

    @Override
    public Object getKey() {
      return v.getRootBean();
    }

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

    @Override
    public String getPath() {
      /*
       * TODO(bobv,nchalko): Determine the correct way to extract this
       * information from the ConstraintViolation.
       */
      return v.getPropertyPath().toString();
    }

    @Override
    public Object getUserDataObject() {
      return v;
    }
  }

  public static Iterable<SimpleViolation> iterableFromConstrantViolations(
      Iterable<ConstraintViolation<?>> violations) {
    return new ConstraintViolationIterable(violations);
  }

  /**
   * Maps an abstract representation of a violation into the appropriate
   * EditorDelegate.
   */
  public static void pushViolations(Iterable<SimpleViolation> violations,
      EditorDriver<?> driver, KeyMethod keyMethod) {
    if (violations == null) {
      return;
    }

    DelegateMap delegateMap = DelegateMap.of(driver, keyMethod);

    // For each violation
    for (SimpleViolation error : violations) {
      Object key = error.getKey();
      List<AbstractEditorDelegate<?, ?>> delegateList = delegateMap.get(key);
      if (delegateList != null) {

        // For each delegate editing some record...
        for (AbstractEditorDelegate<?, ?> baseDelegate : delegateList) {

          // compute its base path in the hierarchy...
          String basePath = baseDelegate.getPath();

          // and the absolute path of the leaf editor receiving the error.
          String absolutePath = (basePath.length() > 0 ? basePath + "." : "")
              + error.getPath();
          final String originalAbsolutePath = absolutePath;
          while (true) {
            if (processLeafDelegates(
                delegateMap, originalAbsolutePath, absolutePath, error)) {
              break;
            } else if (processEditors(
                delegateMap, baseDelegate, absolutePath, error)) {
              break;
            } else {
              // This is guaranteed to never happen because we should always
              // process a delegate/editor if the absolutePath is empty.
              // Still, we have the check here to prevent an infinite
              // loop if something goes wrong.
              if (absolutePath.isEmpty()) {
                throw new IllegalStateException(
                    "No editor: " + originalAbsolutePath);
              }
              absolutePath = getParentPath(absolutePath);
            }
          }
        }
      }
    }
  }

  /**
   * Returns the path with everything after the last '.' stripped off,
   * or "" if there was no '.' in the path.
   */
  private static String getParentPath(String absolutePath) {
    // Traverse upwards in the path to the parents in order
    // to report the error to the nearest valid parent.
    int dotIdx = absolutePath.lastIndexOf('.');
    if (dotIdx > 0) {
      return absolutePath.substring(0, dotIdx);
    }
    return "";
  }

  /**
   * Records an error in any editors that match the path, returning true
   * if any editors matched.
   */
  private static boolean processEditors(DelegateMap delegateMap,
      AbstractEditorDelegate<?, ?> baseDelegate,
      String absolutePath,
      SimpleViolation error) {
    List<Editor<?>> editors = delegateMap.getEditorByPath(absolutePath);
    if (editors == null) {
      return false;
    }
    // No EditorDelegate to attach it to, so record on the baseDelegate
    // with the appropriate editor & path.
    for (Editor<?> editor : editors) {
      baseDelegate.recordError(error.getMessage(), null,
          error.getUserDataObject(), error.getPath(), editor);
    }
    return true;
  }

  /**
   * Records an error in any delegates that match the {@code absolutePath},
   * returning true if any matched.  ({@code originalAbsolutePath}
   * is not used for finding delegates, but is instead used to determine
   * how to record the error.)
   */
  private static boolean processLeafDelegates(DelegateMap delegateMap,
      String originalAbsolutePath,
      String absolutePath,
      SimpleViolation error) {
    // Find the leaf editor's delegate.
    List<AbstractEditorDelegate<?, ?>> leafDelegates =
      delegateMap.getDelegatesByPath(absolutePath);
    if (leafDelegates == null) {
      return false;
    }
    String addlPath = originalAbsolutePath.substring(absolutePath.length());
    for (AbstractEditorDelegate<?, ?> delegate : leafDelegates) {
      // If this is the original path value, don't record the additional path.
      if (addlPath.isEmpty()) {
        delegate.recordError(error.getMessage(), null,
            error.getUserDataObject());
      } else {
        // Otherwise, include the additional path.
        delegate.recordError(error.getMessage(), null,
            error.getUserDataObject(), addlPath,
            delegate.getEditor());
      }
    }
    return true;
  }

  /**
   * Typically constructed via factory methods.
   */
  protected SimpleViolation() {
  }

  /**
   * Return the object that the violation is about.
   */
  public abstract Object getKey();

  /**
   * Return a user-facing message describing the violation.
   */
  public abstract String getMessage();

  /**
   * Return a dotted path describing the property.
   */
  public abstract String getPath();

  /**
   * An object that should be available from
   * {@link com.google.gwt.editor.client.EditorError#getUserData()}.
   */
  public abstract Object getUserDataObject();
}
