/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * 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 git4idea.repo;

import com.intellij.dvcs.repo.Repository;
import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;

/**
 * @author Kirill Likhodedov
 */
public class GitRepoInfo {

  @Nullable private final GitLocalBranch myCurrentBranch;
  @Nullable private final String myCurrentRevision;
  @NotNull private final Repository.State myState;
  @NotNull private final Collection<GitRemote> myRemotes;
  @NotNull private final Collection<GitLocalBranch> myLocalBranches;
  @NotNull private final Collection<GitRemoteBranch> myRemoteBranches;
  @NotNull private final Collection<GitBranchTrackInfo> myBranchTrackInfos;

  public GitRepoInfo(@Nullable GitLocalBranch currentBranch, @Nullable String currentRevision, @NotNull Repository.State state,
                     @NotNull Collection<GitRemote> remotes, @NotNull Collection<GitLocalBranch> localBranches,
                     @NotNull Collection<GitRemoteBranch> remoteBranches, @NotNull Collection<GitBranchTrackInfo> branchTrackInfos) {
    myCurrentBranch = currentBranch;
    myCurrentRevision = currentRevision;
    myState = state;
    myRemotes = remotes;
    myLocalBranches = localBranches;
    myRemoteBranches = remoteBranches;
    myBranchTrackInfos = branchTrackInfos;
  }

  @Nullable
  public GitLocalBranch getCurrentBranch() {
    return myCurrentBranch;
  }

  @NotNull
  public Collection<GitRemote> getRemotes() {
    return myRemotes;
  }

  @NotNull
  public Collection<GitLocalBranch> getLocalBranches() {
    return myLocalBranches;
  }

  @NotNull
  public Collection<GitRemoteBranch> getRemoteBranches() {
    return myRemoteBranches;
  }

  @NotNull
  public Collection<GitBranchTrackInfo> getBranchTrackInfos() {
    return myBranchTrackInfos;
  }

  @Nullable
  public String getCurrentRevision() {
    return myCurrentRevision;
  }

  @NotNull
  public Repository.State getState() {
    return myState;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    GitRepoInfo info = (GitRepoInfo)o;

    if (myState != info.myState) return false;
    if (myCurrentRevision != null ? !myCurrentRevision.equals(info.myCurrentRevision) : info.myCurrentRevision != null) return false;
    if (myCurrentBranch != null ? !myCurrentBranch.equals(info.myCurrentBranch) : info.myCurrentBranch != null) return false;
    if (!myRemotes.equals(info.myRemotes)) return false;
    if (!myBranchTrackInfos.equals(info.myBranchTrackInfos)) return false;
    if (!myLocalBranches.equals(info.myLocalBranches)) return false;
    if (!myRemoteBranches.equals(info.myRemoteBranches)) return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = myCurrentBranch != null ? myCurrentBranch.hashCode() : 0;
    result = 31 * result + (myCurrentRevision != null ? myCurrentRevision.hashCode() : 0);
    result = 31 * result + myState.hashCode();
    result = 31 * result + myRemotes.hashCode();
    result = 31 * result + myLocalBranches.hashCode();
    result = 31 * result + myRemoteBranches.hashCode();
    result = 31 * result + myBranchTrackInfos.hashCode();
    return result;
  }

  @Override
  public String toString() {
    return String.format("GitRepoInfo{current=%s, remotes=%s, localBranches=%s, remoteBranches=%s, trackInfos=%s}",
                         myCurrentBranch, myRemotes, myLocalBranches, myRemoteBranches, myBranchTrackInfos);
  }
}

@@ -660,16 +660,60 @@
 sitory;%0A
+import com.intellij.openapi.util.Comparing;%0A
 import g
@@ -3163,25 +3163,47 @@
 f (!
-myRemotes.equals(
+Comparing.haveEqualElements(myRemotes, 
 info
@@ -3238,16 +3238,44 @@
    if (!
+Comparing.haveEqualElements(
 myBranch
@@ -3284,24 +3284,18 @@
 ackInfos
-.equals(
+, 
 info.myB
@@ -3335,16 +3335,44 @@
    if (!
+Comparing.haveEqualElements(
 myLocalB
@@ -3374,32 +3374,26 @@
 ocalBranches
-.equals(
+, 
 info.myLocal
@@ -3426,16 +3426,44 @@
    if (!
+Comparing.haveEqualElements(
 myRemote
@@ -3470,24 +3470,18 @@
 Branches
-.equals(
+, 
 info.myR
@@ -3815,57 +3815,111 @@
 t + 
-myRemotes.hashCode();%0A    result = 31 * result + 
+hashCodeForCollectionComparison(myRemotes);%0A    result = 31 * result + hashCodeForCollectionComparison(
 myLo
@@ -3925,34 +3925,24 @@
 ocalBranches
-.hashCode(
 );%0A    resul
@@ -3959,16 +3959,48 @@
 esult + 
+hashCodeForCollectionComparison(
 myRemote
@@ -4007,26 +4007,16 @@
 Branches
-.hashCode(
 );%0A    r
@@ -4041,56 +4041,278 @@
 t + 
-myBranchTrackInfos.hashCode();%0A    return result
+hashCodeForCollectionComparison(myBranchTrackInfos);%0A    return result;%0A  %7D%0A%0A  private static %3CT%3E int hashCodeForCollectionComparison(@NotNull Collection%3CT%3E collection) %7B%0A    int i = 0;%0A    for (T element : collection) %7B%0A      i += element.hashCode();%0A    %7D%0A    return i
 ;%0A  

Fix equals & hashcode for GitRepoInfo