/*
 * Copyright 2000-2014 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 com.intellij.vcs.log.graph.impl.print;

import com.intellij.vcs.log.graph.GraphColorManager;
import com.intellij.vcs.log.graph.api.LinearGraph;
import com.intellij.vcs.log.graph.api.elements.GraphEdge;
import com.intellij.vcs.log.graph.api.elements.GraphElement;
import com.intellij.vcs.log.graph.api.elements.GraphNode;
import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo;
import com.intellij.vcs.log.graph.utils.LinearGraphUtils;
import com.intellij.vcs.log.graph.utils.NormalEdge;
import org.jetbrains.annotations.NotNull;

public class ColorGetterByLayoutIndex<CommitId> {
  @NotNull private final LinearGraph myLinearGraph;
  @NotNull private final PermanentGraphInfo<CommitId> myPermanentGraphInfo;
  @NotNull private final GraphColorManager<CommitId> myColorManager;

  public ColorGetterByLayoutIndex(@NotNull LinearGraph linearGraph,
                                  @NotNull PermanentGraphInfo<CommitId> permanentGraphInfo,
                                  @NotNull GraphColorManager<CommitId> colorManager) {
    myLinearGraph = linearGraph;
    myPermanentGraphInfo = permanentGraphInfo;
    myColorManager = colorManager;
  }

  public int getColorId(@NotNull GraphElement element) {
    if (element instanceof GraphNode) {
      int nodeIndex = ((GraphNode)element).getNodeIndex();
      return getNodeColor(nodeIndex, getLayoutIndex(nodeIndex));
    }
    else {
      GraphEdge edge = (GraphEdge)element;
      NormalEdge normalEdge = LinearGraphUtils.asNormalEdge(edge);
      if (normalEdge == null) {
        int nodeIndex = LinearGraphUtils.getNotNullNodeIndex(edge);
        return getNodeColor(nodeIndex, getLayoutIndex(nodeIndex));
      }

      int upLayoutIndex = getLayoutIndex(normalEdge.up);
      int downLayoutIndex = getLayoutIndex(normalEdge.down);

      if (upLayoutIndex >= downLayoutIndex) {
        return getNodeColor(normalEdge.up, upLayoutIndex);
      }

      return getNodeColor(normalEdge.down, downLayoutIndex);
    }
  }

  protected int getNodeColor(int nodeIndex, int layoutIndex) {
    int headNodeId = getHeadNodeId(nodeIndex);
    CommitId headCommitId = myPermanentGraphInfo.getPermanentCommitsInfo().getCommitId(headNodeId);
    if (layoutIndex == myPermanentGraphInfo.getPermanentGraphLayout().getLayoutIndex(headNodeId)) {
      return myColorManager.getColorOfBranch(headCommitId);
    }
    else {
      return myColorManager.getColorOfFragment(headCommitId, layoutIndex);
    }
  }

  private int getHeadNodeId(int upNodeIndex) {
    int nodeId = getNodeId(upNodeIndex);
    if (nodeId < 0) return 0;
    return myPermanentGraphInfo.getPermanentGraphLayout().getOneOfHeadNodeIndex(nodeId);
  }

  private int getLayoutIndex(int upNodeIndex) {
    int nodeId = getNodeId(upNodeIndex);
    if (nodeId < 0) return nodeId;
    return myPermanentGraphInfo.getPermanentGraphLayout().getLayoutIndex(nodeId);
  }

  private int getNodeId(int upNodeIndex) {
    return myLinearGraph.getNodeId(upNodeIndex);
  }
}

@@ -1875,17 +1875,38 @@
 odeI
-ndex = 
+d = myLinearGraph.getNodeId
 ((
+(
 Grap
@@ -1934,16 +1934,17 @@
 eIndex()
+)
 ;%0A      
@@ -1960,36 +1960,33 @@
 tNodeColor(nodeI
-ndex
+d
 , getLayoutIndex
@@ -1983,36 +1983,33 @@
 ayoutIndex(nodeI
-ndex
+d
 ));%0A    %7D%0A    el
@@ -2172,23 +2172,44 @@
 nt nodeI
-ndex = 
+d = myLinearGraph.getNodeId(
 LinearGr
@@ -2238,24 +2238,25 @@
 eIndex(edge)
+)
 ;%0A        re
@@ -2278,20 +2278,17 @@
 or(nodeI
-ndex
+d
 , getLay
@@ -2301,20 +2301,17 @@
 ex(nodeI
-ndex
+d
 ));%0A    
@@ -2311,24 +2311,150 @@
 );%0A      %7D%0A%0A
+      int upNodeId = myLinearGraph.getNodeId(normalEdge.up);%0A      int downNodeId = myLinearGraph.getNodeId(normalEdge.down);%0A
       int up
@@ -2482,29 +2482,24 @@
 utIndex(
-normalEdge.up
+upNodeId
 );%0A     
@@ -2536,31 +2536,26 @@
 utIndex(
-normalEdge.down
+downNodeId
 );%0A%0A    
@@ -2624,29 +2624,24 @@
 deColor(
-normalEdge.up
+upNodeId
 , upLayo
@@ -2685,31 +2685,26 @@
 deColor(
-normalEdge.down
+downNodeId
 , downLa
@@ -2734,15 +2734,13 @@
   pr
-otec
+iva
 te
-d
  int
@@ -2762,20 +2762,17 @@
 nt nodeI
-ndex
+d
 , int la
@@ -2820,28 +2820,25 @@
 NodeId(nodeI
-ndex
+d
 );%0A    Commi
@@ -3227,63 +3227,17 @@
 int 
-upN
+n
 odeI
-ndex) %7B%0A    int nodeId = getNodeId(upNodeIndex);
+d) %7B
 %0A   
@@ -3394,63 +3394,17 @@
 int 
-upN
+n
 odeI
-ndex) %7B%0A    int nodeId = getNodeId(upNodeIndex);
+d) %7B
 %0A   
@@ -3524,104 +3524,7 @@
 %0A  %7D
-%0A%0A  private int getNodeId(int upNodeIndex) %7B%0A    return myLinearGraph.getNodeId(upNodeIndex);%0A  %7D
 %0A%7D%0A

remove excessive getNodeId calls