package com.jetbrains.python.refactoring.classes.pullUp;

import com.google.common.collect.Iterables;
import com.intellij.refactoring.classMembers.MemberInfoModel;
import com.jetbrains.NotNullPredicate;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
import org.easymock.internal.MocksControl;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;

import java.util.ArrayList;
import java.util.List;

/**
 * Tests dependencies management for PyPullUp refactoring
 *
 * @author Ilya.Kazakevich
 */
public class PyPullUpInfoModelTest extends PyTestCase {
  private PyPullUpInfoModel mySut;
  private List<PyMemberInfo<PyElement>> myMemberInfos;


  @Override
  public void setUp() throws Exception {
    super.setUp();
    myFixture.configureByFile("/refactoring/pullup/pyPullUpInfoModel.py");
    final PyClass childClass = getClassByName("ChildWithDependencies");
    final PyClass parentClass = getClassByName("SomeParent");
    mySut = new PyPullUpInfoModel(childClass, new MocksControl(MocksControl.MockType.NICE).createMock(PyPullUpView.class));
    mySut.setSuperClass(parentClass);
    myMemberInfos = new PyMemberInfoStorage(childClass).getClassMemberInfos(childClass);
  }

  /**
   * Checks class field depends on class field
   */
  public void testClassMemberDependencies() throws Exception {
    checkMembers("CLASS_FIELD_DEPENDS_ON_CLASS_FIELD_FOO");
    Assert.assertThat("Class member dependencies failed", getErrorMemberNames(), Matchers.containsInAnyOrder("CLASS_FIELD_FOO"));
  }

  /**
   * Checks instance field depends on class field
   */
  public void testInstanceMemberDependencies() throws Exception {
    checkMembers("self.depends_on_class_field_foo");
    Assert.assertThat("Instance member dependencies failed", getErrorMemberNames(), Matchers.containsInAnyOrder("CLASS_FIELD_FOO"));
  }

  /**
   * Checks method depends on another class field
   */
  public void testMethodMemberDependencies() throws Exception {
    checkMembers("method_depends_on_normal_method(self)");
    Assert.assertThat("Method dependencies failed", getErrorMemberNames(), Matchers.containsInAnyOrder("normal_method(self)"));
  }

  /**
   * Checks method depends on method
   */
  public void testMethodOnInstanceMemberDependencies() throws Exception {
    checkMembers("method_depends_on_instance_field_bar(self)");
    Assert.assertThat("Instance on member dependencies failed", getErrorMemberNames(), Matchers.containsInAnyOrder("self.instance_field_bar"));
  }

  /**
   * Check dependnecies for properties, declared in old-style
   *
   */
  public void testOldProperty() throws Exception {
    checkMembers("method_depends_on_old_property(self)");
    Assert.assertThat("Method on old property dependency failed", getErrorMemberNames(), Matchers.containsInAnyOrder(
      "old_property",
      "old_property_2",
      "old_property_3"));
  }

  /**
   *
   * Check dependnecies for properties, declared in new-style
   */
  public void testNewProperty() throws Exception {
    checkMembers("method_depends_on_new_property(self)");
    Assert.assertThat("Method on new property dependency failed", getErrorMemberNames(), Matchers.containsInAnyOrder("new_property", "new_property_2"));
  }


  /**
   * All dependencies are met: new (destination) class has all of them
   */
  public void testParentDependenciesOk() throws Exception {
    checkMembers("CLASS_FIELD_DEPENDS_ON_PARENT_FIELD",
                 "method_depends_on_parent_method(self)",
                 "method_depends_on_parent_field(self)");
    Assert.assertThat("Dependence check false positive: parent has all required members", getErrorMemberNames(), Matchers.empty());
  }


  /**
   * New (destination) class has no members, required by member under refactoring.
   * Error should be displayed.
   */
  public void testNoParentDependenciesOk() throws Exception {
    mySut.setSuperClass(getClassByName("EmptyParent"));
    checkMembers("CLASS_FIELD_DEPENDS_ON_PARENT_FIELD",
                 "method_depends_on_parent_method(self)",
                 "method_depends_on_parent_field(self)");
    Assert.assertThat("Dependence check false positive: parent has all required members", getErrorMemberNames(), Matchers.contains("extends SomeParent"));
  }


  /**
   * @return names of error members (displayed with red)
   */
  @NotNull
  private List<String> getErrorMemberNames() {
    final List<String> result = new ArrayList<String>();
    for (final PyMemberInfo<PyElement> info : myMemberInfos) {
      if (mySut.checkForProblems(info) != MemberInfoModel.OK) {
        result.add(info.getDisplayName());
      }
    }
    return result;
  }

  /**
   * Marks members to be moved (sets checkbox on them)
   * @param memberNames names of members to check
   */
  private void checkMembers(@NotNull final String... memberNames) {
    for (final String memberName : memberNames) {
      Iterables.find(myMemberInfos, new NamePredicate(memberName)).setChecked(true);
    }
    mySut.memberInfoChanged(myMemberInfos);
  }

  private static class NamePredicate extends NotNullPredicate<PyMemberInfo<?>> {
    @NotNull
    private final String myNameToSearch;

    private NamePredicate(@NotNull final String nameToSearch) {
      myNameToSearch = nameToSearch;
    }

    @Override
    protected boolean applyNotNull(@NotNull final PyMemberInfo<?> input) {
      return input.getDisplayName().equals(myNameToSearch);
    }
  }
}
