// Copyright 2017 Google Inc.
//
// 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 codeu.chat.client.core;

import java.util.ArrayList;
import java.util.Collection;

import codeu.chat.common.BasicView;
import codeu.chat.common.ConversationHeader;
import codeu.chat.common.ConversationPayload;
import codeu.chat.common.Message;
import codeu.chat.common.NetworkCode;
import codeu.chat.common.User;
import codeu.chat.common.ServerInfo;
import codeu.chat.util.Logger;
import codeu.chat.util.Serializers;
import codeu.chat.util.Time;
import codeu.chat.util.Uuid;
import codeu.chat.util.connections.Connection;
import codeu.chat.util.connections.ConnectionSource;

// VIEW
//
// This is the view component of the Model-View-Controller pattern used by the
// the client to reterive readonly data from the server. All methods are blocking
// calls.
final class View implements BasicView {

  private final static Logger.Log LOG = Logger.newLog(View.class);

  private final ConnectionSource source;

  public View(ConnectionSource source) {
    this.source = source;
  }

  public ServerInfo getInfo() {
    try (final Connection connection = this.source.connect()) {
      Serializers.INTEGER.write(connection.out(), NetworkCode.SERVER_INFO_REQUEST);
      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.SERVER_INFO_RESPONSE) {
        final Uuid version = Uuid.SERIALIZER.read(connection.in());
        return new ServerInfo(version);
      } else {
        LOG.error("Unexpected Server Response.");
      }
    } catch (Exception ex) {
      System.out.println("ERROR: Exception while connecting. Check log for details.");
      LOG.error(ex, "Connection error occurred");
    }
    // If we get here it means something went wrong and null should be returned
    return null;
  }

  @Override
  public Collection<User> getUsers() {

    final Collection<User> users = new ArrayList<>();

    try (final Connection connection = source.connect()) {

      Serializers.INTEGER.write(connection.out(), NetworkCode.GET_USERS_REQUEST);

      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.GET_USERS_RESPONSE) {
        users.addAll(Serializers.collection(User.SERIALIZER).read(connection.in()));
      } else {
        LOG.error("Response from server failed.");
      }

    } catch (Exception ex) {
      System.out.println("ERROR: Exception during call on server. Check log for details.");
      LOG.error(ex, "Exception during call on server.");
    }

    return users;
  }

  @Override
  public Collection<ConversationHeader> getConversations() {

    final Collection<ConversationHeader> summaries = new ArrayList<>();

    try (final Connection connection = source.connect()) {

      Serializers.INTEGER.write(connection.out(), NetworkCode.GET_ALL_CONVERSATIONS_REQUEST);

      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.GET_ALL_CONVERSATIONS_RESPONSE) {
        summaries.addAll(Serializers.collection(ConversationHeader.SERIALIZER).read(connection.in()));
      } else {
        LOG.error("Response from server failed.");
      }

    } catch (Exception ex) {
      System.out.println("ERROR: Exception during call on server. Check log for details.");
      LOG.error(ex, "Exception during call on server.");
    }

    return summaries;
  }

  @Override
  public Collection<ConversationPayload> getConversationPayloads(Collection<Uuid> ids) {

    final Collection<ConversationPayload> conversations = new ArrayList<>();

    try (final Connection connection = source.connect()) {

      Serializers.INTEGER.write(connection.out(), NetworkCode.GET_CONVERSATIONS_BY_ID_REQUEST);
      Serializers.collection(Uuid.SERIALIZER).write(connection.out(), ids);

      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.GET_CONVERSATIONS_BY_ID_RESPONSE) {
        conversations.addAll(Serializers.collection(ConversationPayload.SERIALIZER).read(connection.in()));
      } else {
        LOG.error("Response from server failed.");
      }
    } catch (Exception ex) {
      System.out.println("ERROR: Exception during call on server. Check log for details.");
      LOG.error(ex, "Exception during call on server.");
    }

    return conversations;
  }

  @Override
  public Collection<Message> getMessages(Collection<Uuid> ids) {

    final Collection<Message> messages = new ArrayList<>();

    try (final Connection connection = source.connect()) {

      Serializers.INTEGER.write(connection.out(), NetworkCode.GET_MESSAGES_BY_ID_REQUEST);
      Serializers.collection(Uuid.SERIALIZER).write(connection.out(), ids);

      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.GET_MESSAGES_BY_ID_RESPONSE) {
        messages.addAll(Serializers.collection(Message.SERIALIZER).read(connection.in()));
      } else {
        LOG.error("Response from server failed.");
      }
    } catch (Exception ex) {
      System.out.println("ERROR: Exception during call on server. Check log for details.");
      LOG.error(ex, "Exception during call on server.");
    }

    return messages;
  }

  public ServerInfo getInfo() {
    try (final Connection connection = source.connect()) {
      Serializers.INTEGER.write(connection.out(), NetworkCode.SERVER_INFO_REQUEST);
      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.SERVER_INFO_RESPONSE) {
        final Time startTime = Time.SERIALIZER.read(connection.in());
        return new ServerInfo(startTime);
      } else {
      // Communicate this error - the server did not respond with the type of
      // response we expected.
        System.out.println("ERROR: Server did not respond with correct type of response.");
        //LOG.error("Response from server failed.");
      }
    } catch (Exception ex) {
      // Communicate this error - something went wrong with the connection.
        System.out.println("ERROR: Exception during call on server.");
        //LOG.error(ex, "Exception during call on server.");
    }
      // If we get here it means something went wrong and null should be returned
        return null;
  }

}

@@ -1901,32 +1901,102 @@
 nnection.in());%0A
+        final Time startTime = Time.SERIALIZER.read(connection.in());%0A
         return n
@@ -2016,16 +2016,27 @@
 (version
+, startTime
 );%0A     
@@ -5635,1013 +5635,6 @@
   %7D%0A
-%0A  public ServerInfo getInfo() %7B%0A    try (final Connection connection = source.connect()) %7B%0A      Serializers.INTEGER.write(connection.out(), NetworkCode.SERVER_INFO_REQUEST);%0A      if (Serializers.INTEGER.read(connection.in()) == NetworkCode.SERVER_INFO_RESPONSE) %7B%0A        final Time startTime = Time.SERIALIZER.read(connection.in());%0A        return new ServerInfo(startTime);%0A      %7D else %7B%0A      // Communicate this error - the server did not respond with the type of%0A      // response we expected.%0A        System.out.println(%22ERROR: Server did not respond with correct type of response.%22);%0A        //LOG.error(%22Response from server failed.%22);%0A      %7D%0A    %7D catch (Exception ex) %7B%0A      // Communicate this error - something went wrong with the connection.%0A        System.out.println(%22ERROR: Exception during call on server.%22);%0A        //LOG.error(ex, %22Exception during call on server.%22);%0A    %7D%0A      // If we get here it means something went wrong and null should be returned%0A        return null;%0A  %7D%0A%0A
 %7D%0A

fix merge conflicts in View