import React from 'react'
import PropTypes from 'prop-types'
import Component from '../utils/Component'
import classnames from 'classnames'
import {warning,getScrollTop,getClientHeight} from '../utils/Tool'
import Logger from '../utils/logger'

import '../style'
import 'phoenix-styles/less/modules/image.less'

/**
 * 图片组件<br/>
 * - 和普通图片使用方式一致,src为必填选项,可自行添加alt属性。
 * - 可通过defaultSrc添加默认图片地址,在图片未加载出来之前显示。
 * - 可通过phSize设置图片大小,default为宽高和父级一致;cover为覆盖,不变形,没有空白区域;contain包含,不变形,可能有空白区域。
 * - 可通过lazy设置图片为懒加载的模式,当图片进入视口之后才开始加载,可配合ImageList使用。
 * - 可通过loadCallback设置图片加载完成的回调函数。
 * - cover和contain必须设置定高。
 *
 * 主要属性和接口:
 * - src: 图片地址。<br/>
 * 如:`<Image src={IMAGE_URL} alt='图片没有加载上的提示语'/>`
 * - defaultSrc: 默认图片地址。<br/>
 * 如:`<Image src={IMAGE_URL} defaultSrc={DEFAULT_URL}/>`
 * - phSize: 图片大小。<br/>
 * 如:`<Image src={IMAGE_URL} phSize='cover'/>`
 * - lazy: 是否懒加载<br/>
 * 如:`<Image src={IMAGE_URL} lazy/>`
 * - loadCallback: 图片加载完成的回调<br/>
 * 如:`<Image src={IMAGE_URL} loadCallback={(err)=>{if(!err) console.log('success!')}}/>`
 * 
 * @class Image
 * @module 基础组件
 * @extends Component
 * @constructor
 * @since 2.0.0
 * @demo image|image.js {展示}
 * @show true
 * */

export default class Images extends Component{
    static propTypes = {
        /**
         * 样式前缀
         * @property classPrefix
         * @type String
         * @default 'image'
         * */
        classPrefix: PropTypes.string,        
        /**
         * 图片地址
         * @property src
         * @type String
         * @default null
         * */
        src: PropTypes.string,
        /**
         * 默认图片地址
         * @property defaultSrc
         * @type String
         * @default null
         * */
        defaultSrc: PropTypes.string,
        /**
         * 图片大小,[default, cover, contain]
         * @property phSize
         * @type String
         * @default 'default'
         * */
        phSize: PropTypes.oneOf(['default','cover','contain']),
        /**
         * 是否懒加载
         * @property lazy
         * @type Boolean
         * @default false
         * */
        lazy: PropTypes.bool,
        /**
         * 图片加载完成的回调
         * @property loadCallback
         * @type Function
         * @default null
         * */
        loadCallback: PropTypes.func
    };

    static defaultProps ={
        src: null,
        defaultSrc: null,
        lazy: false,
        phSize: 'default',
        classPrefix:'image',
        classMapping : {}
    };

    constructor(props,context){
        super(props,context)

        new Logger('Image')

        this.load = false

        // 对默认图片预加载
        this.defaultImagePreload()

        this.state = {
            src: props.defaultSrc || null
        }

        this.scrollHandle = this.scrollHandle.bind(this)
        if(props.lazy) window.addEventListener('scroll', this.scrollHandle, false)
    }

    componentWillReceiveProps(nextProps){
        let {src, defaultSrc, lazy} = nextProps

        if(this.state.src !== src){
            this.load = false

            this.setState({
                src: defaultSrc || null
            }, ()=>{
                if(nextProps.lazy) window.addEventListener('scroll', this.scrollHandle, false)
                this.isLazyCallback(nextProps)
            })
        }
    }

    defaultImagePreload(){
        let {defaultSrc} = this.props

        if(defaultSrc){
            let img = new Image()
            img.src = defaultSrc
        }
    }

    scrollHandle(){
        this.lazyLoad()
    }

    lazyLoad(){
        this.scrollTop = getScrollTop()
        this.bodyHeight = getClientHeight()
        this.imageTop = this.phImage.offsetTop

        if(this.scrollTop + this.bodyHeight >= this.imageTop){
            console.log('lazyLoad')
            if(!this.load) {
                this.imageLoad(true)
            }
        }
    }

    componentDidMount(){
        this.isLazyCallback(this.props)
    }

    isLazyCallback(props){
        let {lazy} = props
        
        if(lazy && !this.load){
            this.lazyLoad()
        }else{
            this.imageLoad()
        }
    }

    getImageSize(){
        let {phSize} = this.props

        switch(phSize){
            case 'cover':
                if(this.imageWidth>this.imageHeight){
                    this.image.style.height = '100%'
                }else{
                    this.image.style.width = '100%'
                }
                break
            case 'contain':
                if(this.imageWidth>this.imageHeight){
                    this.image.style.width = '100%'
                }else{
                    this.image.style.height = '100%'
                }
                break
            default:
                this.image.style.width = '100%'
                this.image.style.height = '100%'
        }
    }

    imageLoad(isLazy){
        let {src, loadCallback} = this.props

        try{
            let img = new Image()
            img.src = src

            this.load = true
            console.log(src)
            if(img.complete){ // 如果已经存在,直接加载
                this.loadSuccessCallback(img, isLazy)
                return
            }

            img.onload = (e)=>{ // 否则等到图片加载完成
                img.onload = null
                this.loadSuccessCallback(img, isLazy)
            }
        }catch(err){
            if(loadCallback) loadCallback(err)
        }
    }

    loadSuccessCallback(img, isLazy){
        let {src, lazy, loadCallback} = this.props
        if(lazy) window.removeEventListener('scroll', this.scrollHandle, false)

        this.isLazy = isLazy

        this.setState({src: src})

        this.imageWidth = img.width
        this.imageHeight = img.height

        this.getImageSize()
        if(loadCallback) loadCallback()
    }

    componentWillUnmount(){
        window.removeEventListener('scroll', this.scrollHandle, false)
    }

    renderImage(){
        let {className, style, alt, children} = this.props;

        return (
            <div className={classnames(this.getProperty(true), className)} 
                ref={(phImage)=>{this.phImage=phImage}}
                style={this.getStyles(style)}
            >
                <img {...this.otherProps} className='' src={this.state.src} ref={(image)=>{this.image=image}} />
            </div>
        )
    }

    render(){
        return this.renderImage();
    }
}