//Copyright (C) 2013 The Android Open Source Project
//
// 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.gerrit.client.diff;

import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;

import net.codemirror.lib.CodeMirror;

/**
 * A table with one row and two columns to hold the two CodeMirrors displaying
 * the files to be diffed.
 */
class DiffTable extends Composite {
  interface Binder extends UiBinder<HTMLPanel, DiffTable> {}
  private static final Binder uiBinder = GWT.create(Binder.class);

  interface DiffTableStyle extends CssResource {
    String fullscreen();
    String intralineBg();
    String dark();
    String diff();
    String noIntraline();
    String activeLine();
    String range();
    String rangeHighlight();
    String showTabs();
    String showLineNumbers();
    String hideA();
    String columnMargin();
    String padding();
  }

  @UiField Element cmA;
  @UiField Element cmB;
  @UiField OverviewBar overview;
  @UiField Element patchSetNavRow;
  @UiField Element patchSetNavCellA;
  @UiField Element patchSetNavCellB;
  @UiField Element diffHeaderRow;
  @UiField Element diffHeaderText;
  @UiField FlowPanel widgets;
  @UiField static DiffTableStyle style;

  @UiField(provided = true)
  PatchSetSelectBox2 patchSetSelectBoxA;

  @UiField(provided = true)
  PatchSetSelectBox2 patchSetSelectBoxB;

  private SideBySide2 parent;
  private boolean header;
  private boolean headerVisible;
  private boolean visibleA;

  DiffTable(SideBySide2 parent, PatchSet.Id base, PatchSet.Id revision,
      String path) {
    patchSetSelectBoxA = new PatchSetSelectBox2(
        parent, DisplaySide.A, revision.getParentKey(), base, path);
    patchSetSelectBoxB = new PatchSetSelectBox2(
        parent, DisplaySide.B, revision.getParentKey(), revision, path);
    PatchSetSelectBox2.link(patchSetSelectBoxA, patchSetSelectBoxB);

    initWidget(uiBinder.createAndBindUi(this));
    this.parent = parent;
    this.headerVisible = true;
    this.visibleA = true;
  }

  boolean isVisibleA() {
    return visibleA;
  }

  void setVisibleA(boolean show) {
    visibleA = show;
    if (show) {
      removeStyleName(style.hideA());
    } else {
      addStyleName(style.hideA());
    }
  }

  Runnable toggleA() {
    return new Runnable() {
      @Override
      public void run() {
        setVisibleA(!isVisibleA());
      }
    };
  }

  boolean isHeaderVisible() {
    return headerVisible;
  }

  void setHeaderVisible(boolean show) {
    headerVisible = show;
    UIObject.setVisible(patchSetNavRow, show);
    UIObject.setVisible(diffHeaderRow, show && header);
    if (show) {
      parent.header.removeStyleName(style.fullscreen());
    } else {
      parent.header.addStyleName(style.fullscreen());
    }
    parent.resizeCodeMirror();
  }

  int getHeaderHeight() {
    int h = patchSetSelectBoxA.getOffsetHeight();
    if (header) {
      h += diffHeaderRow.getOffsetHeight();
    }
    return h;
  }

  void set(JsArray<RevisionInfo> list, DiffInfo info) {
    patchSetSelectBoxA.setUpPatchSetNav(list, info.meta_a());
    patchSetSelectBoxB.setUpPatchSetNav(list, info.meta_b());

    JsArrayString hdr = info.diff_header();
    StringBuilder b = new StringBuilder();
    for (int i = 1; i < hdr.length(); i++) {
      String s = hdr.get(i);
      if (s.startsWith("diff --git ")
          || s.startsWith("index ")
          || s.startsWith("+++ ")
          || s.startsWith("--- ")) {
        continue;
      }
      b.append(s).append('\n');
    }
    header = b.length() > 0;
    diffHeaderText.setInnerText(b.toString().trim());
    UIObject.setVisible(diffHeaderRow, header);
  }

  void refresh() {
    overview.refresh();
    if (header) {
      CodeMirror cm = parent.getCmFromSide(DisplaySide.A);
      diffHeaderText.getStyle().setMarginLeft(
          cm.getGutterElement().getOffsetWidth(),
          Unit.PX);
    }
  }

  void add(Widget widget) {
    widgets.add(widget);
  }
}

@@ -4334,24 +4334,49 @@
 f_header();%0A
+    if (hdr != null) %7B%0A  
     StringBu
@@ -4410,16 +4410,18 @@
 ();%0A    
+ 
+ 
 for (int
@@ -4449,24 +4449,26 @@
 h(); i++) %7B%0A
+  
       String
@@ -4486,24 +4486,26 @@
 t(i);%0A      
+  
 if (s.starts
@@ -4520,24 +4520,26 @@
 ff --git %22)%0A
+  
           %7C%7C
@@ -4564,32 +4564,34 @@
 ex %22)%0A          
+  
 %7C%7C s.startsWith(
@@ -4600,32 +4600,34 @@
 ++ %22)%0A          
+ 
+ 
 %7C%7C s.startsWith(
@@ -4645,16 +4645,18 @@
         
+  
 continue
@@ -4659,26 +4659,30 @@
 inue;%0A      
-%7D%0A
+  %7D%0A  
       b.appe
@@ -4709,39 +4709,92 @@
     
-%7D%0A    header = b.length() %3E 0;%0A
+  %7D%0A%0A      String hdrTxt = b.toString().trim();%0A      header = !hdrTxt.isEmpty();%0A  
     
@@ -4825,30 +4825,19 @@
 ext(
-b.toString().trim()
+hdrTxt
 );%0A
+  
     
@@ -4880,16 +4880,106 @@
 eader);%0A
+    %7D else %7B%0A      header = false;%0A      UIObject.setVisible(diffHeaderRow, false);%0A    %7D%0A
   %7D%0A%0A  v

Allow missing diff_header in JSON reply