// 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.change;

import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class History extends FlowPanel {
  private CommentLinkProcessor clp;
  private ReplyAction replyAction;
  private Change.Id changeId;

  private final Map<Integer, List<CommentInfo>> byAuthor = new HashMap<>();

  void set(CommentLinkProcessor clp, ReplyAction ra, Change.Id id, ChangeInfo info) {
    this.clp = clp;
    this.replyAction = ra;
    this.changeId = id;

    JsArray<MessageInfo> messages = info.messages();
    if (messages != null) {
      for (MessageInfo msg : Natives.asList(messages)) {
        Message ui = new Message(this, msg);
        ui.addComments(comments(msg));
        add(ui);
      }
      autoOpen(ChangeScreen.myLastReply(info));
    }
  }

  private void autoOpen(Timestamp lastReply) {
    if (lastReply == null) {
      for (Widget child : getChildren()) {
        ((Message) child).autoOpen();
      }
    } else {
      for (int i = getChildren().size() - 1; i >= 0; i--) {
        Message ui = (Message) getChildren().get(i);
        MessageInfo msg = ui.getMessageInfo();
        if (lastReply.compareTo(msg.date()) < 0) {
          ui.autoOpen();
        } else {
          break;
        }
      }
    }
  }

  CommentLinkProcessor getCommentLinkProcessor() {
    return clp;
  }

  Change.Id getChangeId() {
    return changeId;
  }

  void replyTo(MessageInfo info) {
    replyAction.onReply(info);
  }

  void addComments(NativeMap<JsArray<CommentInfo>> map) {
    for (String path : map.keySet()) {
      for (CommentInfo c : Natives.asList(map.get(path))) {
        c.path(path);
        if (c.author() != null) {
          int authorId = c.author()._accountId();
          List<CommentInfo> l = byAuthor.get(authorId);
          if (l == null) {
            l = new ArrayList<>();
            byAuthor.put(authorId, l);
          }
          l.add(c);
        }
      }
    }
  }

  private List<CommentInfo> comments(MessageInfo msg) {
    if (msg.author() == null) {
      return Collections.emptyList();
    }

    int authorId = msg.author()._accountId();
    List<CommentInfo> list = byAuthor.get(authorId);
    if (list == null) {
      return Collections.emptyList();
    }

    Timestamp when = msg.date();
    List<CommentInfo> match = new ArrayList<>();
    List<CommentInfo> other = new ArrayList<>();
    for (CommentInfo c : list) {
      if (c.updated().compareTo(when) <= 0) {
        match.add(c);
      } else {
        other.add(c);
      }
    }
    if (match.isEmpty()) {
      return Collections.emptyList();
    } else if (other.isEmpty()) {
      byAuthor.remove(authorId);
    } else {
      byAuthor.put(authorId, other);
    }
    return match;
  }
}
