/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.fresco.vito.view;

import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import com.facebook.common.internal.Preconditions;
import com.facebook.drawee.drawable.VisibilityCallback;
import com.facebook.fresco.vito.core.FrescoContext;
import com.facebook.fresco.vito.core.FrescoDrawable;
import com.facebook.fresco.vito.core.FrescoState;
import com.facebook.fresco.vito.listener.ImageListener;
import com.facebook.fresco.vito.options.ImageOptions;
import com.facebook.imagepipeline.multiuri.MultiUri;

/** You must initialize this class before use by calling {#code VitoView.init()}. */
@Deprecated /* Experimental */
public class VitoViewImpl implements VitoView.Implementation {

  private final FrescoContext mFrescoContext;

  private final View.OnAttachStateChangeListener sOnAttachStateChangeListenerCallback =
      new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View view) {
          onAttach(view);
        }

        @Override
        public void onViewDetachedFromWindow(View view) {
          onDetach(view);
        }
      };

  public VitoViewImpl(FrescoContext frescoContext) {
    mFrescoContext = frescoContext;
  }

  @Override
  public void show(
      @Nullable Uri uri,
      @Nullable MultiUri multiUri,
      ImageOptions imageOptions,
      @Nullable Object callerContext,
      @Nullable ImageListener imageListener,
      final View target) {
    Preconditions.checkArgument(
        !(uri != null && multiUri != null), "Setting both a Uri and MultiUri is not allowed!");

    FrescoDrawable frescoDrawable;
    final Drawable background = target.getBackground();
    if (background instanceof FrescoDrawable) {
      frescoDrawable = (FrescoDrawable) background;
    } else {
      frescoDrawable = new FrescoDrawable(true);
      ViewCompat.setBackground(target, frescoDrawable);
    }

    frescoDrawable.setVisibilityCallback(
        new VisibilityCallback() {
          @Override
          public void onVisibilityChange(boolean visible) {
            if (!visible) {
              onDetach(target);
            }
          }

          @Override
          public void onDraw() {
            // NOP
          }
        });

    final FrescoState oldState = getState(target);
    final FrescoState state =
        mFrescoContext
            .getController()
            .onPrepare(
                oldState,
                uri,
                multiUri,
                imageOptions,
                callerContext,
                target.getResources(),
                imageListener);
    state.setFrescoDrawable(frescoDrawable);
    setState(target, state);

    // `addOnAttachStateChangeListener` is not idempotent
    target.removeOnAttachStateChangeListener(sOnAttachStateChangeListenerCallback);
    target.addOnAttachStateChangeListener(sOnAttachStateChangeListenerCallback);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      // If the view is already attached, we should tell this to controller.
      if (target.isAttachedToWindow()) {
        onAttach(target);
      }
    } else {
      // Before Kitkat we don't have a good way to know.
      // Normally we expect the view to be already attached, thus we always call `onAttach`.
      onAttach(target);
    }
  }

  private void onAttach(View view) {
    onAttach(getState(view));
  }

  private void onDetach(View view) {
    onDetach(getState(view));
  }

  private void onAttach(@Nullable FrescoState state) {
    if (state != null && !state.isAttached()) {
      mFrescoContext.getController().onAttach(state, null);
    }
  }

  private void onDetach(@Nullable FrescoState state) {
    if (state != null && state.isAttached()) {
      mFrescoContext.getController().onDetach(state);
    }
  }

  private static void setState(View view, FrescoState state) {
    view.setTag(R.id.fresco_vito_tag_state, state);
  }

  @Nullable
  private static FrescoState getState(View view) {
    return (FrescoState) view.getTag(R.id.fresco_vito_tag_state);
  }
}

@@ -1899,665 +1899,8 @@
 );%0A%0A
-    FrescoDrawable frescoDrawable;%0A    final Drawable background = target.getBackground();%0A    if (background instanceof FrescoDrawable) %7B%0A      frescoDrawable = (FrescoDrawable) background;%0A    %7D else %7B%0A      frescoDrawable = new FrescoDrawable(true);%0A      ViewCompat.setBackground(target, frescoDrawable);%0A    %7D%0A%0A    frescoDrawable.setVisibilityCallback(%0A        new VisibilityCallback() %7B%0A          @Override%0A          public void onVisibilityChange(boolean visible) %7B%0A            if (!visible) %7B%0A              onDetach(target);%0A            %7D%0A          %7D%0A%0A          @Override%0A          public void onDraw() %7B%0A            // NOP%0A          %7D%0A        %7D);%0A%0A
     
@@ -2261,53 +2261,8 @@
 r);%0A
-    state.setFrescoDrawable(frescoDrawable);%0A
     
@@ -2938,62 +2938,957 @@
 ate 
-void onAttach(View view) %7B%0A    onAttach(getState(view)
+FrescoDrawable createFrescoDrawable(final View target) %7B%0A    FrescoDrawable frescoDrawable;%0A    final Drawable background = target.getBackground();%0A    if (background instanceof FrescoDrawable) %7B%0A      frescoDrawable = (FrescoDrawable) background;%0A    %7D else %7B%0A      frescoDrawable = new FrescoDrawable(true);%0A      ViewCompat.setBackground(target, frescoDrawable);%0A    %7D%0A%0A    frescoDrawable.setVisibilityCallback(%0A        new VisibilityCallback() %7B%0A          @Override%0A          public void onVisibilityChange(boolean visible) %7B%0A            if (!visible) %7B%0A              onDetach(target);%0A            %7D%0A          %7D%0A%0A          @Override%0A          public void onDraw() %7B%0A            // NOP%0A          %7D%0A        %7D);%0A    return frescoDrawable;%0A  %7D%0A%0A  private void onAttach(View view) %7B%0A    FrescoDrawable frescoDrawable = createFrescoDrawable(view);%0A    FrescoState state = getState(view);%0A    state.setFrescoDrawable(frescoDrawable);%0A    onAttach(state
 );%0A 

Set frescoDrawable when view is re-attached