content: /*
   * Copyright (C) 2017 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.android.internal.widget;
  
  import android.app.ActivityManager;
  import android.app.Notification;
  import android.view.View;
  
  import java.util.Objects;
  
  /**
   * A message of a {@link MessagingLayout}.
   */
  public interface MessagingMessage extends MessagingLinearLayout.MessagingChild {
  
      /**
       * Prefix for supported image MIME types
       **/
      String IMAGE_MIME_TYPE_PREFIX = "image/";
  
      static MessagingMessage createMessage(MessagingLayout layout,
              Notification.MessagingStyle.Message m, ImageResolver resolver) {
          if (hasImage(m) && !ActivityManager.isLowRamDeviceStatic()) {
              return MessagingImageMessage.createMessage(layout, m, resolver);
          } else {
              return MessagingTextMessage.createMessage(layout, m);
          }
      }
  
      static void dropCache() {
          MessagingTextMessage.dropCache();
          MessagingImageMessage.dropCache();
      }
  
      static boolean hasImage(Notification.MessagingStyle.Message m) {
          return m.getDataUri() != null
                  && m.getDataMimeType() != null
                  && m.getDataMimeType().startsWith(IMAGE_MIME_TYPE_PREFIX);
      }
  
      /**
       * Set a message for this view.
       * @return true if setting the message worked
       */
      default boolean setMessage(Notification.MessagingStyle.Message message) {
          getState().setMessage(message);
          return true;
      }
  
      default Notification.MessagingStyle.Message getMessage() {
          return getState().getMessage();
      }
  
      default boolean sameAs(Notification.MessagingStyle.Message message) {
          Notification.MessagingStyle.Message ownMessage = getMessage();
          if (!Objects.equals(message.getText(), ownMessage.getText())) {
              return false;
          }
          if (!Objects.equals(message.getSender(), ownMessage.getSender())) {
              return false;
          }
          boolean hasRemoteInputHistoryChanged = message.isRemoteInputHistory()
                  != ownMessage.isRemoteInputHistory();
          // When the remote input history has changed, we want to regard messages equal even when
          // the timestamp changes. The main reason is that the message that the system inserts
          // will have a different time set than the one that the app will update us with and we
          // still want to reuse that message.
          if (!hasRemoteInputHistoryChanged
                  && !Objects.equals(message.getTimestamp(), ownMessage.getTimestamp())) {
              return false;
          }
          if (!Objects.equals(message.getDataMimeType(), ownMessage.getDataMimeType())) {
              return false;
          }
          if (!Objects.equals(message.getDataUri(), ownMessage.getDataUri())) {
              return false;
          }
          return true;
      }
  
      default boolean sameAs(MessagingMessage message) {
          return sameAs(message.getMessage());
      }
  
      default void removeMessage() {
          getGroup().removeMessage(this);
      }
  
      default void setMessagingGroup(MessagingGroup group) {
          getState().setGroup(group);
      }
  
      default void setIsHistoric(boolean isHistoric) {
          getState().setIsHistoric(isHistoric);
      }
  
      default MessagingGroup getGroup() {
          return getState().getGroup();
      }
  
      default void setIsHidingAnimated(boolean isHiding) {
          getState().setIsHidingAnimated(isHiding);
      }
  
      @Override
      default boolean isHidingAnimated() {
          return getState().isHidingAnimated();
      }
  
      @Override
      default void hideAnimated() {
          setIsHidingAnimated(true);
          getGroup().performRemoveAnimation(getView(), () -> setIsHidingAnimated(false));
      }
  
      default boolean hasOverlappingRendering() {
          return false;
      }
  
      default void recycle() {
          getState().recycle();
      }
  
      default View getView() {
          return (View) this;
      }
  
      default void setColor(int textColor) {}
  
      MessagingMessageState getState();
  
      void setVisibility(int visibility);
  
      int getVisibility();
  }
  