/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.taobao.weex.ui.component;

import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;
import android.widget.FrameLayout;

import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.annotation.Component;
import com.taobao.weex.adapter.URIAdapter;
import com.taobao.weex.common.Constants;
import com.taobao.weex.ui.action.BasicComponentData;
import com.taobao.weex.ui.view.WXVideoView;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXUtils;

import java.util.HashMap;
import java.util.Map;
@Component(lazyload = false)

public class WXVideo extends WXComponent<FrameLayout> {

  private boolean mAutoPlay;
  private WXVideoView.Wrapper mWrapper;

  /**
   * package
   **/
  boolean mPrepared;
  private boolean mError;

  @Deprecated
  public WXVideo(WXSDKInstance instance, WXVContainer parent, String instanceId, boolean isLazy, BasicComponentData basicComponentData) {
    this(instance, parent, isLazy, basicComponentData);
  }

  public WXVideo(WXSDKInstance instance, WXVContainer parent, boolean isLazy, BasicComponentData basicComponentData) {
    super(instance, parent, isLazy, basicComponentData);
  }

  @Override
  protected FrameLayout initComponentHostView(@NonNull Context context) {
    final WXVideoView.Wrapper video = new WXVideoView.Wrapper(context);

    video.setOnErrorListener(new MediaPlayer.OnErrorListener() {

      @Override
      public boolean onError(MediaPlayer mp, int what, int extra) {
        if (WXEnvironment.isApkDebugable()) {
          WXLogUtils.d("Video", "onError:" + what);
        }
        video.getProgressBar().setVisibility(View.GONE);
        mPrepared = false;
        mError = true;

        if (getEvents().contains(Constants.Event.FAIL)) {
          WXVideo.this.notify(Constants.Event.FAIL, Constants.Value.STOP);
        }
        return true;
      }
    });

    video.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

      @Override
      public void onPrepared(MediaPlayer mediaPlayer) {
        if (WXEnvironment.isApkDebugable()) {
          WXLogUtils.d("Video", "onPrepared");
        }
        video.getProgressBar().setVisibility(View.GONE);
        mPrepared = true;
        if (mAutoPlay) {
          video.start();
        }

        //callback from video view, so videoview should not null
        WXVideoView videoView = video.getVideoView();
        videoView.seekTo(5);

        if (video.getMediaController() != null) {
          if (!mStopped) {
            video.getMediaController().show(3);
          } else {
            video.getMediaController().hide();
          }
        }

        mStopped = false;
      }
    });

    video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

      @Override
      public void onCompletion(MediaPlayer mediaPlayer) {
        if (WXEnvironment.isApkDebugable()) {
          WXLogUtils.d("Video", "onCompletion");
        }
        if (getEvents().contains(Constants.Event.FINISH)) {
          WXVideo.this.notify(Constants.Event.FINISH, Constants.Value.STOP);
        }
      }
    });

    video.setOnVideoPauseListener(new WXVideoView.VideoPlayListener() {

      @Override
      public void onPause() {
        if (WXEnvironment.isApkDebugable()) {
          WXLogUtils.d("Video", "onPause");
        }
        if (getEvents().contains(Constants.Event.PAUSE)) {
          WXVideo.this.notify(Constants.Event.PAUSE, Constants.Value.PAUSE);
        }
      }

      @Override
      public void onStart() {
        if (WXEnvironment.isApkDebugable()) {
          WXLogUtils.d("Video", "onStart");
        }

        if (getEvents().contains(Constants.Event.START)) {
          WXVideo.this.notify(Constants.Event.START, Constants.Value.PLAY);
        }
      }
    });
    mWrapper = video;
    return video;
  }

  private void notify(String event, String newStatus) {
    Map<String, Object> params = new HashMap<>(2);
    params.put(Constants.Name.PLAY_STATUS, newStatus);
    params.put("timeStamp", System.currentTimeMillis());

    Map<String, Object> domChanges = new HashMap<>();
    Map<String, Object> attrsChanges = new HashMap<>();
    attrsChanges.put(Constants.Name.PLAY_STATUS, newStatus);
    domChanges.put("attrs", attrsChanges);

    WXSDKManager.getInstance().fireEvent(getInstanceId(), getRef(), event, params, domChanges);
  }

  @Override
  public void bindData(WXComponent component) {
    super.bindData(component);
    addEvent(Constants.Event.APPEAR);
  }

  @Override
  public void notifyAppearStateChange(String wxEventType, String direction) {
    super.notifyAppearStateChange(wxEventType, direction);
    mWrapper.createVideoViewIfVisible();
  }

  @Override
  public void destroy() {
    super.destroy();
  }

  @Override
  protected boolean setProperty(String key, Object param) {
    switch (key) {
      case Constants.Name.SRC:
        String src = WXUtils.getString(param, null);
        if (src != null) {
          setSrc(src);
        }
        return true;
      case Constants.Name.AUTO_PLAY:
        Boolean result = WXUtils.getBoolean(param, null);
        if (result != null) {
          setAutoPlay(result);
        }
        return true;
      case Constants.Name.PLAY_STATUS:
        String status = WXUtils.getString(param, null);
        if (status != null) {
          setPlaystatus(status);
        }
        return true;
    }
    return super.setProperty(key, param);
  }

  @WXComponentProp(name = Constants.Name.SRC)
  public void setSrc(String src) {
    if (TextUtils.isEmpty(src) || getHostView() == null) {
      return;
    }

    if (!TextUtils.isEmpty(src)) {
      WXSDKInstance instance = getInstance();
      mWrapper.setVideoURI(instance.rewriteUri(Uri.parse(src), URIAdapter.VIDEO));
      mWrapper.getProgressBar().setVisibility(View.VISIBLE);
    }
  }

  @WXComponentProp(name = Constants.Name.AUTO_PLAY)
  public void setAutoPlay(boolean autoPlay) {
    mAutoPlay = autoPlay;
    if(autoPlay){
      mWrapper.createIfNotExist();
      mWrapper.start();
    }
  }

  private boolean mStopped;

  @WXComponentProp(name = Constants.Name.PLAY_STATUS)
  public void setPlaystatus(String playstatus) {

    if (mPrepared && !mError && !mStopped) {
      if (playstatus.equals(Constants.Value.PLAY)) {
        mWrapper.start();
      } else if (playstatus.equals(Constants.Value.PAUSE)) {
        mWrapper.pause();
      } else if (playstatus.equals(Constants.Value.STOP)) {
        mWrapper.stopPlayback();
        mStopped = true;
      }
    } else if ((mError || mStopped) && playstatus.equals(Constants.Value.PLAY)) {
      mError = false;
      mWrapper.resume();

      mWrapper.getProgressBar().setVisibility(View.VISIBLE);
    }
  }
}
