import React, { useState, useEffect, useRef, useMemo, useContext } from 'react';
import {
  View,
  Text,
  StyleSheet,
  Dimensions,
  PanResponder,
  ScrollView,
  Image,
  Platform,
  StatusBar,
  TouchableOpacity,
  Share,
  BackHandler
} from 'react-native';
import Modal from 'react-native-modal';
import { Slider, Icon } from 'react-native-elements';
import Animated, { Easing } from 'react-native-reanimated';
import { State, PanGestureHandler } from 'react-native-gesture-handler';
import { getStatusBarHeight } from '../utils/StatusBarHeight';
import C from 'rn-class';
import PlayerControls from './PlayerControls';
import PlayerContents from './PlayerContents';
import PlayerHeader from './PlayerHeader';
import { getInset } from 'react-native-safe-area-view';
import Video from 'react-native-video';
import { PlayerDispatchContext, PlayerStateContext } from './PlayerReducer';

const { width, height } = Dimensions.get('window');
const statusBarHeight = getStatusBarHeight(true);
const minHeight = height * 0.1;
const midBound = height - height / 2.5;
const upperBound = midBound + minHeight;
//const destination = height - height * 0.2
//const destination = height - height*0.16 -2 - getStatusBarHeight(true);
//getInset('bottom')
// height > 560
// ?height * 0.75 - getInset('bottom')
// :height * 0.70;

const {
  Value,
  event,
  Extrapolate,
  cond,
  Clock,
  eq,
  set,
  add,
  sub,
  multiply,
  lessThan,
  clockRunning,
  startClock,
  spring,
  stopClock,
  interpolate,
  timing,
  neq,
  or,
  and,
  greaterThan,
  call
} = Animated;

const shadow = {
  alignItems: 'center',
  shadowColor: 'black',
  shadowOffset: { width: 0, height: 0 },
  shadowOpacity: 0.18,
  shadowRadius: 2
};
const shadow2 = {
  alignItems: 'center',
  shadowColor: '#000',
  shadowOffset: {
    width: 0,
    height: 7
  },
  shadowOpacity: 0.41,
  shadowRadius: 9.11

  //elevation: 14
};

const shadowShare = {
  shadowColor: '#000',
  shadowOffset: {
    width: 0,
    height: 7
  },
  shadowOpacity: 0.41,
  shadowRadius: 9.11,
  elevation: 14
};

const shadowImage = {
  shadowColor: '#000',
  shadowOffset: {
    width: 0,
    height: 2
  },
  shadowOpacity: 0.25,
  shadowRadius: 3.84,

  elevation: 5
};

function runSpring(clock, value, dest) {
  const state = {
    finished: new Value(0),
    velocity: new Value(0),
    position: new Value(0),
    time: new Value(0)
  };

  const config = {
    damping: 20,
    mass: 1,
    stiffness: 100,
    overshootClamping: false,
    restSpeedThreshold: 1,
    restDisplacementThreshold: 0.5,
    toValue: new Value(0)
  };

  return [
    cond(clockRunning(clock), 0, [
      set(state.finished, 0),
      set(state.velocity, 0),
      set(state.position, value),
      set(config.toValue, dest),
      startClock(clock)
    ]),
    spring(clock, state, config),
    cond(state.finished, stopClock(clock)),
    state.position
  ];
}

const onShare = async () => {
  try {
    const result = await Share.share({
      message: '페이스북 | https://facebook.com'
    });

    if (result.action === Share.sharedAction) {
      if (result.activityType) {
        // shared with activity type of result.activityType
      } else {
        // shared
      }
    } else if (result.action === Share.dismissedAction) {
      // dismissed
    }
  } catch (error) {
    alert(error.message);
  }
};

/**
 *  애니메이션 offset 값 설정
 */
const animatedOffset = {y:0};
const getAnimatedOffset = (v) => {
  animatedOffset.y = v[0];
}

export default props => {
  const [modalVisible, setModalVisible] = useState(null);
  const { y: tabY } = props.tabPosition;
  const destination = tabY - minHeight - statusBarHeight;
  const [currentPlayerValue, setCurrentPlayerValue] = useState(0);
  const [isPlay, setPlay] = useState(false);
  const { playerData } = props;
  const {
    onGestureEvent,
    translateY,
    opacity,
    playContainerWidth,
    playerContainerHeight,
    videoWidth,
    videoHeight,
    playerControlOpaciy,
    playerBoderRadius,
    mainPlayerContainerHeight,
    PlayerHeadWidth,
    PlayerHeadHeight,
    PlayerHeadOpacity,
    slideDown
  } = useMemo(() => {

    const translationY = new Value(0);
    const velocityY = new Value(0);
    const offsetY = new Value(0);
    const offsetY2 = new Value(0);
    const gestureState = new Value(State.UNDETERMINED);
    const clockY = new Clock();
    const finalTranslateY = add(translationY, multiply(0.2, velocityY));
    const absoluteY = new Value(0);
    /**
     *  snapPoint 제스처가 끝날 때 위치 지정을 해주는 값
     *  TabBar 의 높이가 해상도와 스크린에서 그려지는 값이 틀려 TabBar 에서
     *  onLayout 이벤트를 이용하여 TabBar의 y 값을 가져와 처리
     *  destination 변수가 플레이어 축소 시 y 값 높이
     */
    const snapPoint = cond(
      lessThan(finalTranslateY, sub(offsetY, height / 4)),
      0,
      destination
    );
    const ty = cond(
      and(eq(gestureState, State.END), neq(translationY, 0)),
      [
        call([offsetY],getAnimatedOffset),
        set(
          translationY,
          runSpring(clockY, add(offsetY, translationY), snapPoint)
        ),
        set(offsetY, translationY),
        translationY
      ],
      [
        cond(eq(gestureState, State.BEGAN), 
        [
          stopClock(clockY),
          cond(neq(offsetY2, 0), [
            
          ]),
        ]),
        add(offsetY, translationY)
      ]
    );

    const translateY = add(ty, offsetY2);

    const slideDown = () => timing(offsetY, {
      toValue: destination,
      duration: 500,
      easing: Easing.inOut(Easing.ease),
    }).start();

    return {
      translateY,
      slideDown,
      onGestureEvent: event(
        [
          {
            nativeEvent: {
              translationY,
              velocityY,
              state: gestureState,
              absoluteY
            }
          }
        ],
        { useNativeDriver: true }
      ),
      opacity: interpolate(translateY, {
        inputRange: [0, midBound],
        outputRange: [1, 0],
        extrapolate: Extrapolate.CLAMP
      }),
      playContainerWidth: interpolate(translateY, {
        inputRange: [0, midBound],
        outputRange: [width, width - 16],
        extrapolate: Extrapolate.CLAMP
      }),
      playerContainerHeight: interpolate(translateY, {
        inputRange: [0, midBound],
        outputRange: [height, 0],
        extrapolate: Extrapolate.CLAMP
      }),
      videoWidth: interpolate(translateY, {
        inputRange: [0, midBound, upperBound],
        outputRange: [width, width - 16, width / 4],
        extrapolate: Extrapolate.CLAMP
      }),
      videoHeight: interpolate(translateY, {
        inputRange: [0, midBound, upperBound],
        outputRange: [width / 1.78, minHeight * 1.3, minHeight],
        extrapolate: Extrapolate.CLAMP
      }),
      playerControlOpaciy: interpolate(translateY, {
        inputRange: [midBound, upperBound],
        outputRange: [0, 1],
        extrapolate: Extrapolate.CLAMP
      }),
      playerBoderRadius: interpolate(translateY, {
        inputRange: [midBound, upperBound],
        outputRange: [0, 15],
        extrapolate: Extrapolate.CLAMP
      }),
      mainPlayerContainerHeight: interpolate(translateY, {
        inputRange: [0, midBound, upperBound],
        outputRange: [height, minHeight * 1.3, minHeight],
        extrapolate: Extrapolate.CLAMP
      }),
      PlayerHeadWidth: interpolate(translateY, {
        inputRange: [0, width],
        outputRange: [width, 0],
        extrapolate: Extrapolate.CLAMP
      }),
      PlayerHeadHeight: interpolate(translateY, {
        inputRange: [0, 50],
        outputRange: [50, 0],
        extrapolate: Extrapolate.CLAMP
      }),
      PlayerHeadOpacity: interpolate(translateY, {
        inputRange: [0, minHeight],
        outputRange: [1, 0],
        extrapolate: Extrapolate.CLAMP
      })
    };
  }, []);

  /**
   *  android backbutton handle
   */
  const backButtonHandler = () => {
    if(~~animatedOffset.y < ~~destination) {
      slideDown();
    }
    return true;
  }

  useEffect(() => {
    BackHandler.addEventListener('hardwareBackPress', backButtonHandler)
    playerDispatch({type:'currentTime', setCurrentTime: 0});
    return () => {
      BackHandler.removeEventListener('hardwareBackPress', backButtonHandler)
      playerDispatch({type:'currentTime', setCurrentTime: 0});
    };
  },[playerData.soundURI]);

  const player = useRef(null);
  
  const playerDispatch = useContext(PlayerDispatchContext);
  const { uri, paused, muted } = useContext(PlayerStateContext);
  const playerOnBuffer = (data) => {
    // console.log('bufffer::: ' + data)
  }
  const playerOnError = (e) => {
    console.log(e);
  }
  const playerOnLoad = (data) => {
    //console.log(data)
    let duration=0;
    data.duration < 0 ? duration=1 : duration=data.duration
    playerDispatch({type:'paused', setPaused:false});
    playerDispatch({type:'duration', setDuraton: Math.floor(duration)});
  }
  const playerOnProgress = (data) => {
    // console.log(data.currentTime)
    playerDispatch({type:'currentTime', setCurrentTime: data.currentTime});
  }
  const onLoadStart = (e) => {
    //console.log('onload start',e);
    playerDispatch({type:'player', player: player});
  }
  const playerOnEnd = () => {
    //console.log('end');
  }
  const onSeek = (data) => {
    //console.log(data)
    if(data.seekTime===0 && data.currentTime===0) {
      playerDispatch({type:'paused', setPaused: true});
      playerDispatch({type:'currentTime', setCurrentTime: 0});
    }
  }
  return (
        <>
        {/* <C.View
            style={{ ...StyleSheet.absoluteFillObject, zIndex: 1000, marginTop:getStatusBarHeight(true) }}
            cls="h20 bgc-rgba-white-0_5"
          >
            <C.Text cls="f5 ta-c bgc-rgba-red-0_5">테스트용 Component</C.Text>
            <C.View cls="h10 ai-c bgc-rgba-blue-0_5">
              <Slider
                style={{ width: '95%' }}
                trackStyle={{ height: 2 }}
                thumbTintColor="#333"
                thumbStyle={{ width: 10, height: 5 }}
                value={currentPlayerValue}
                onValueChange={value => setCurrentPlayerValue(value)}
              />
              <C.View cls="w95 jc-sb flx-row">
                <C.Text>Time : {currentPlayerValue}</C.Text>
              </C.View>
            </C.View>
            <C.TouchableOpacity 
              cls="h5 bgc-rgba-black-0_5"
              onPress={() => {
                setPlay(!isPlay);
              }}
            >
              <C.Text cls="f5 ta-c rgba-white-0_5">Click Test</C.Text>
            </C.TouchableOpacity>
          </C.View> */}
          <PanGestureHandler
            onHandlerStateChange={onGestureEvent}
            activeOffsetY={[-10, 10]}
            onGestureEvent={onGestureEvent}
          >
            <Animated.View
              style={{
                ...StyleSheet.absoluteFillObject,
                zIndex: 10,
                marginTop: statusBarHeight,
                transform: [{ translateY }],
                alignItems: 'center',
                height: mainPlayerContainerHeight
              }}
            >
              <Animated.View
                style={{
                  padding: 0,
                  backgroundColor: 'white',
                  width: playContainerWidth,
                  borderRadius: playerBoderRadius
                }}
              >
                <Animated.View
                  style={[
                    Platform.OS === 'android'
                      ? { borderColor: '#eee' }
                      : { borderColor: 'white' },
                    {
                      ...StyleSheet.absoluteFillObject,
                      borderWidth: 1,
                      borderRadius: 15,
                      opacity: playerControlOpaciy,
                      backgroundColor: 'white'
                    },
                    shadow2
                  ]}
                >
                  <PlayerControls
                    {...props}
                  />
                </Animated.View>
                <Animated.View
                  style={{
                    opacity: PlayerHeadOpacity,
                    backgroundColor: 'rgba(255,255,255,0)',
                    width: PlayerHeadWidth,
                    height: PlayerHeadHeight
                  }}
                >
                  <PlayerHeader {...props} visibleMenu={setModalVisible} />
                </Animated.View>
                <Animated.View style={{ width: videoWidth, height: videoHeight }}>
                  <Animated.Image
                    resizeMode="contain"
                    style={{ flex: 1, margin: 10, width: null, height: null }}
                    source={{uri: playerData.img}}
                    />
                  <Video
                    source={{uri:playerData.soundURI}}
                    style={StyleSheet.absoluteFill}
                    ref={player}
                    //rate={this.state.rate}
                    paused={paused}
                    //volume={this.state.volume}
                    muted={muted}
                    //ignoreSilentSwitch={this.state.ignoreSilentSwitch}
                    resizeMode='contain'
                    onLoad={playerOnLoad}
                    onLoadStart={onLoadStart}
                    onBuffer={playerOnBuffer}
                    onProgress={playerOnProgress}
                    onSeek={onSeek}
                    onError={playerOnError}
                    onEnd={playerOnEnd}
                    //poster='https://baconmockup.com/300/200/'
                    repeat={true}
                    //filter={this.state.filter}
                    //filterEnabled={this.state.filterEnabled}
                    audioOnly={true}
                  />
                </Animated.View>
              </Animated.View>
              <Animated.View
                style={{
                  backgroundColor: 'white',
                  width: playContainerWidth,
                  height: playerContainerHeight
                }}
              >
                <Animated.View style={{ opacity }}>
                  <PlayerContents
                    {...props}
                  />
                </Animated.View>
              </Animated.View>
            </Animated.View>
          </PanGestureHandler>
          <Modal
            isVisible={modalVisible === 'detail'}
            onSwipeComplete={() => {
              setModalVisible(null);
            }}
            swipeDirection="left"
            //deviceHeight={height}
            deviceWidth={width}
            style={{ margin: 0 }}
            backdropColor="white"
            backdropOpacity={1}
            animationIn="slideInLeft"
            animationOut="slideOutLeft"
          >
            <C.View cls="w90 h100 bgc-rgba-black-0_5">
              <ScrollView style={{ flex: 1, marginTop: '10%' }}>
                <C.Text cls="flx1 fw-b ta-c">{playerData.title}</C.Text>
                <C.View cls="flx2 ph5 mt5">
                  <C.Text cls="fw-b">{playerData.title}</C.Text>
                  <C.Text cls="mt2">{playerData.content}</C.Text>
                  <C.Text cls="mt3" numberOfLines={1}>
                    {/* by {playerData.author.replace(/\r\n|\n|\r/gm, ' ')} */}
                  </C.Text>
                  <C.Text cls="mt5 as-e" numberOfLines={1}>
                    {playerData.date}
                  </C.Text>
                </C.View>
              </ScrollView>
            </C.View>
            <TouchableOpacity
              style={[
                StyleSheet.absoluteFillObject,
                {
                  width: '90%',
                  justifyContent: 'center',
                  paddingRight: '5%',
                  alignItems: 'flex-end'
                }
              ]}
              onPress={() => {
                setModalVisible(null);
              }}
            >
              <C.EL.Icon
                color="rgb(10,132,255)"
                {...C.n2cls('size10')}
                type="ionicon"
                name="md-arrow-dropleft"
              />
            </TouchableOpacity>
          </Modal>

          <Modal isVisible={modalVisible === 'share'} style={{ margin: 0 }}>
            <View
              style={{
                flex: 1,
                justifyContent: 'center',
                alignItems: 'center',
                backgroundColor: 'rgb(242,242,247)'
              }}
            >
              <ScrollView>
                <View style={{ height: statusBarHeight }} />
                <View style={{ marginHorizontal: '5%', alignItems: 'flex-end' }}>
                  <C.EL.Icon
                    color="black"
                    {...C.n2cls('size10')}
                    type="ionicon"
                    name="md-close"
                    onPress={() => {
                      setModalVisible(null);
                    }}
                  />
                </View>

                <View
                  style={{
                    //...shadowImage,
                    //backgroundColor: 'white',
                    marginHorizontal: '5%',
                    width: width * 0.8,
                    height: (width * 0.8) / 1.78
                  }}
                >
                  <Image
                    resizeMode="contain"
                    style={{
                      flex: 1,
                      marginVertical: 10,
                      width: null,
                      height: null
                    }}
                    source={{uri:playerData.img}}
                  />
                </View>
                <C.View cls="flx-row jc-sa ai-t mt2">
                  <C.Text cls="fw-b">{playerData.title}</C.Text>
                  <C.Text cls="fw-b">{playerData.duration}</C.Text>
                </C.View>

                <View style={{ height: minHeight }} />

                <TouchableOpacity
                  onPress={onShare}
                  style={{ marginHorizontal: '5%', alignItems: 'center' }}
                >
                  <View style={[s.sharContainer]}>
                    <C.EL.Icon
                      color="black"
                      {...C.n2cls('size10')}
                      type="ionicon"
                      name="md-share"
                    />
                    <C.Text cls="f2.5">공유하기, 메세지 보내기</C.Text>
                  </View>
                </TouchableOpacity>

                <View style={{ height: minHeight }} />
              </ScrollView>
            </View>
          </Modal>
        </>
  );
};

const s = StyleSheet.create({
  sharContainer: {
    backgroundColor: 'white',
    flexDirection: 'row',
    justifyContent: 'space-around',
    alignItems: 'center',
    borderColor: '#ddd',
    borderRadius: 15,
    flex: 1,
    width: width * 0.8,
    height: minHeight,
    ...shadowShare
  }
});
