/*
 * 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.dom.WXDomObject;
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, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) {
    this(instance, dom, parent, isLazy);
  }

  public WXVideo(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, boolean isLazy) {
    super(instance, dom, parent, isLazy);
  }

  @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 ( getDomObject().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 ( getDomObject().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 ( getDomObject().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 ( getDomObject().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);
    }
  }
}
