code: /*
   *
   *     Copyright (C) 2015 Ingo Fuchs
   *     This program is free software; you can redistribute it and/or modify
   *     it under the terms of the GNU General Public License as published by
   *     the Free Software Foundation; either version 2 of the License, or
   *     (at your option) any later version.
   *
   *     This program is distributed in the hope that it will be useful,
   *     but WITHOUT ANY WARRANTY; without even the implied warranty of
   *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *     GNU General Public License for more details.
   *
   *     You should have received a copy of the GNU General Public License along
   *     with this program; if not, write to the Free Software Foundation, Inc.,
   *     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   * /
   */
  
  package freed.views.shutter;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.os.Build;
  import android.os.Handler;
  import android.os.HandlerThread;
  import android.text.TextUtils;
  import android.util.AttributeSet;
  
  import androidx.appcompat.widget.AppCompatButton;
  
  import com.troop.freedcam.R;
  
  import javax.inject.Inject;
  
  import dagger.hilt.android.AndroidEntryPoint;
  import freed.cam.apis.CameraApiManager;
  import freed.cam.apis.basecamera.CameraWrapperInterface;
  import freed.cam.event.capture.CaptureStates;
  import freed.cam.event.module.ModuleChangedEvent;
  import freed.settings.SettingKeys;
  import freed.settings.SettingsManager;
  import freed.utils.Log;
  
  /**
   * Created by troop on 20.06.2015.
   */
  @AndroidEntryPoint
  public class ShutterButton extends AppCompatButton implements ModuleChangedEvent, freed.cam.event.capture.CaptureStateChangedEvent {
  
      private CameraWrapperInterface cameraUiWrapper;
  
      private final String TAG = ShutterButton.class.getSimpleName();
      protected HandlerThread mBackgroundThread;
      protected ShutterAnimationHandler animationHandler;
      private final Handler uiHandler = new Handler();
  
      @Inject
      public SettingsManager settingsManager;
      @Inject
      CameraApiManager cameraApiManager;
  
      /**
       * Starts a background thread and its {@link Handler}.
       */
      private void startBackgroundThread() {
          if (mBackgroundThread ==  null || !mBackgroundThread.isAlive()) {
              mBackgroundThread = new HandlerThread("ShutterDraw");
              mBackgroundThread.start();
              animationHandler = new ShutterAnimationHandler(mBackgroundThread.getLooper(), getResources(), this);
          }
      }
  
      /**
       * Stops the background thread and its {@link Handler}.
       */
      private void stopBackgroundThread()
      {
          Log.d(TAG, "stopShutterDraw");
          if (mBackgroundThread == null)
              return;
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
              mBackgroundThread.quitSafely();
          } else
              mBackgroundThread.quit();
          try {
              mBackgroundThread.join();
              mBackgroundThread = null;
              animationHandler = null;
          } catch (InterruptedException e) {
              Log.WriteEx(e);
          }
      }
  
      public ShutterButton(Context context, AttributeSet attrs) {
          super(context, attrs);
          this.init(context);
      }
  
      public ShutterButton(Context context) {
          super(context);
          this.init(context);
      }
  
      @Override
      protected void onAttachedToWindow() {
          super.onAttachedToWindow();
          startBackgroundThread();
          Log.d(TAG, "EventBus register");
          if(cameraApiManager != null) {
              cameraApiManager.addCaptureStateChangedEventListner(this);
              cameraApiManager.addModuleChangedEventListner(this);
          }
          //EventBusHelper.register(this);
          invalidate();
      }
  
      @Override
      protected void onDetachedFromWindow() {
          super.onDetachedFromWindow();
          Log.d(TAG, "EventBus unregister");
          cameraApiManager.removeCaptureStateChangedListner(this);
          cameraApiManager.removeModuleChangedEventListner(this);
          stopBackgroundThread();
      }
  
      private void init(Context context) {
  
          startBackgroundThread();
          //set background img that get then overdrawn
          setBackgroundResource(R.drawable.shutter5);
  
          this.setOnClickListener(v -> {
              String sf = settingsManager.get(SettingKeys.SELF_TIMER).get();
              if (TextUtils.isEmpty(sf))
                  sf = "0";
              int selftimer = Integer.parseInt(sf);
              if(selftimer > 0) {
                  uiHandler.postDelayed(selftimerRunner, selftimer*1000);
                  setCaptureState(CaptureStates.selftimerstart);
              }
              else
                  cameraUiWrapper.getModuleHandler().startWork();
          });
  
      }
  
      private final Runnable selftimerRunner =new Runnable() {
          @Override
          public void run() {
              setCaptureState(CaptureStates.selftimerstop);
              cameraUiWrapper.getModuleHandler().startWork();
          }
      };
  
  
      public void SetCameraUIWrapper(CameraWrapperInterface cameraUiWrapper) {
          if (cameraUiWrapper.getModuleHandler() == null)
              return;
          this.cameraUiWrapper = cameraUiWrapper;
          if(cameraUiWrapper.getModuleHandler().getCurrentModule() != null) {
              setCaptureState(cameraUiWrapper.getModuleHandler().getCurrentModule().getCurrentCaptureState());
  
          }
          Log.d(this.TAG, "Set cameraUiWrapper to ShutterButton");
      }
  
      private void setCaptureState(CaptureStates mode) {
          if(mode == null || animationHandler == null) {
              Log.d(TAG, "onCaptureStateChanged: Capture State is null");
              return;
          }
          //first start shutter animation
          animationHandler.setCaptureState(mode);
          Log.d(TAG, "switchBackground:" + mode);
          if (!animationHandler.isRunning())
              animationHandler.startDrawing();
  
          //set specfic mode overides like drawtimer,
          //setting it that way shutter is already abit opend till the green timer gets visible
          switch (mode) {
              case video_recording_stop:
                  animationHandler.drawTimer(false);
                  animationHandler.stopShutterTimer();
                  break;
              case video_recording_start:
                  animationHandler.drawTimer(true);
                  break;
              case image_capture_stop:
                  animationHandler.drawTimer(false);
                  animationHandler.stopShutterTimer();
                  break;
              case image_capture_start:
                  animationHandler.drawTimer(true);
                  break;
              case continouse_capture_start:
                  break;
              case continouse_capture_stop:
                  break;
              case continouse_capture_work_start:
                  animationHandler.drawTimer(true);
                  break;
              case continouse_capture_work_stop:
                  animationHandler.drawTimer(false);
                  break;
              case cont_capture_stop_while_working:
                  break;
              case cont_capture_stop_while_notworking:
                  animationHandler.drawTimer(false);
                  animationHandler.stopShutterTimer();
                  break;
              case selftimerstart:
                  animationHandler.drawTimer(true);
                  break;
              case selftimerstop:
                  animationHandler.drawTimer(false);
                  animationHandler.stopShutterTimer();
          }
      }
  
      @Override
      protected void onDraw(Canvas canvas)
      {
          super.onDraw(canvas);
          animationHandler.onDraw(canvas);
      }
  
      @Override
      public void onModuleChanged(String module) {
          if (cameraUiWrapper == null)
              return;
          if(cameraUiWrapper.getModuleHandler().getCurrentModule() != null) {
              setCaptureState(cameraUiWrapper.getModuleHandler().getCurrentModule().getCurrentCaptureState());
          }
      }
  
      @Override
      public void onCaptureStateChanged(CaptureStates states) {
          setCaptureState(states);
      }
  }