import React from "react";
import PropTypes from 'prop-types';

import IDUtil from '../../util/IDUtil';
import Query from '../../model/Query';
import FlexRouter from '../../util/FlexRouter';
import LocalStorageHandler from '../../util/LocalStorageHandler';
import Loading from '../shared/Loading';

//So this viewer basically fetches the entity based on the provided entityID and
//then applies an entity mapping (for that entity type) by fetching it from the collectionConfig
export default class QuickEntityViewer extends React.Component {

    constructor(props) {
        super(props);
        this.CLASS_PREFIX = "qev";
        this.state = {
            entityData : {} // per entity type stores the entity data
        };
    }

    componentDidMount = () => {
        const entityTypeConfig = this.__getEntityTypeConfig(
            this.props.collectionConfig,
            this.props.entityType
        );
        //if the collection config information about which person properties to show is available
        if(entityTypeConfig && typeof(entityTypeConfig.fetchEntityDetails) === "function") {
            entityTypeConfig.fetchEntityDetails(
                this.props.entityID,
                this.__updateEntityData
            )
        } else {
            console.error("Missing entity details function for entity type " + this.props.entityType);
        }
    };

    __updateEntityData = data => {
        const entityData = this.state.entityData;
        entityData[this.props.entityType] = data && !data['error'] ? data : null;
        this.setState({
            entityData : entityData
        });
    };

    //TODO move this function to the collectionconfig or somewhere else that all compoments can easily use
    __getEntityTypeConfig = (collectionConfig, entityType) => {
        const entityConfig = collectionConfig ? collectionConfig.getEntityConfig() : null;
        if(!entityConfig || !entityConfig[entityType]) return null;

        return entityConfig[entityType];
    };

    onSearch = (entityData) => {
        const entityTypeConfig = this.__getEntityTypeConfig(
            this.props.collectionConfig,
            this.props.entityType
        );
        let otherLabels = entityData[this.props.entityType]["OtherLabels"].map(label => label.value);
        let entity = entityTypeConfig.formatEntityForSearch(this.props.entityID,
        entityData[this.props.entityType]["Name"][0]['value'], //this is the first prefLabel so should be the GTAA label
        otherLabels);

        //create query
        const query = Query.construct({term: "", entities: [entity], fieldCategory: this.props.fieldCategories}, this.props.collectionConfig);

        //store the query in the cache
        LocalStorageHandler.storeJSONInLocalStorage(
            'stored-search-results',
            {query: query} //only the query, the Search page will fill the results
        );
        //open the Search page
        FlexRouter.gotoSingleSearch('cache');
    };

    //Note: this function now assumes that the imageUrl can handle the width parameter, which
    //of course is not standard. For now this is fine, since we only have entity data from wikimedia commons wired up:
    //https://commons.wikimedia.org/wiki/Special:FilePath/someimage.jpg?width=200px
    //Should we link entities to other sources, we should adapt this function (and the entityConfig)
    toBrowserFriendlyImage = imageUrl => imageUrl + '?width=200px';

    //TODO render the image much nicer
    renderEntityImage = (entityData, entityType) => {
        if(!entityData || !entityData[entityType]) return null;

        if(!entityData[entityType].ImageUrl || entityData[entityType].ImageUrl.length === 0) return null;
      
        let imgSrc = entityData[entityType].ImageUrl[0].value;

        return (
            <tr className="poster">
                <td colSpan="2">
                    <div style={{width: '200px'}}>
                        <picture>
                            <source srcSet={this.toBrowserFriendlyImage(imgSrc)} />
                            <img src={imgSrc} alt="image of person" style={{width:'100%'}}/>
                        </picture>
                    </div>
                </td>
            </tr>);
    }

    //TODO render this in a nicer way.
    renderEntityMetadata = (entityData, entityType) => {

        if(!entityData || !entityData[entityType]) return null;
        const details = [];
        Object.entries(entityData[entityType]).forEach(([propertyName, valueList], i)=> {
            details.push(
                <tr  className={IDUtil.cssClassName('id', this.CLASS_PREFIX)} key={'props__key__' + i}>
                    <td colSpan="2"><span className="prop-name">{propertyName}</span></td>
                </tr>
            );
            if(valueList && typeof(valueList) === "object" && valueList.length !== undefined) {
                valueList.forEach((value, j)=> {
                    let valueText = value['valueLabel'] ? value['valueLabel']: value['value']
                    if(valueText.startsWith("http")) {
                        details.push(
                            <tr key={'subprops__' + i + '__'+ j}>
                                <td></td><td><a href={valueText} target='_blank'>{valueText}</a></td>
                            </tr>
                        );
                    } else {
                        details.push(
                            <tr key={'subprops__' + i + '__'+ j}>
                                <td></td><td>{valueText}</td>
                            </tr>
                        );
                    }
                });
            }
        });
        return details.length > 0 ? details : null;
    };

    renderLoadMessage = () => <tr><td>
        Loading information...
        &nbsp;
        <div className="spinner-border">
            <span className="sr-only">Loading...</span>
        </div>
    </td></tr>;

    renderSources = (entityData, entityType) => {
        if(!entityData || typeof(entityData) !== "object" || !entityData[entityType]) return null;
        if(!entityData[entityType].Source || entityData[entityType].Source.length === 0) return null;

                let entityLabel = 'this ' + entityType;
        if(entityType === 'person' && entityData[entityType]["Name"] && entityData[entityType]["Name"].length > 0) {
            entityLabel = `${entityData[entityType]["Name"][0]['value']}`;
        }
        const details = [];
        const sourceList = entityData[entityType].Source
        if(sourceList && typeof(sourceList ) === "object" && sourceList.length !== undefined) {
                        sourceList.forEach((value, j)=> {
                    let sourceLabel = value['valueLabel'] ? value['valueLabel']: value['value']
                    let source = value['value'] ? value['value']: null
                    details.push(
                        <tr key={'subprops__' + j}>
                            <td><a href={source} target='_blank'>Click here to view {entityLabel} in {sourceLabel}</a></td>
                        </tr>
                    );
                });
        }

        return details
    }
    renderSearchButton = (entityID, entityData, entityType) => {

        if(!entityData || typeof(entityData) !== "object" || !entityData[entityType]) return null;

        let entityLabel = 'this ' + entityType;
        if(entityType === 'person' && entityData[entityType]["Name"] && entityData[entityType]["Name"].length > 0) {
            entityLabel = `${entityData[entityType]["Name"][0]['value']}`;
        }
        //TODO more entity types

        return (
            <tr>
                <td colSpan="2">
                    <div className="actions">
                        <button className="btn-secondary" onClick={() => {this.onSearch(entityData)}}>
                            Search for {entityLabel} in the current collection
                        </button>
                    </div>
                </td>
            </tr>
        );
    }

    render() {
        //render the image of the person if available
        const personImage = this.renderEntityImage(this.state.entityData, this.props.entityType);

        const links = this.renderSources(this.state.entityData, this.props.entityType);
        const sourceLinks = links ? links : this.renderLoadMessage();

        //for each property in the data, display the label in a row, with
        //the values in the rows below
        //Entity metadata is excluded at present as the current thinking is to link through to the external source
        //const entityMetadata = this.renderEntityMetadata(this.state.entityData, this.props.entityType);
        //const tableData = entityMetadata ? entityMetadata : this.renderLoadMessage();

        const searchButton = this.renderSearchButton(this.props.entityID, this.state.entityData, this.props.entityType)

        //build a table with all the parts of the person data
        const classNames = ['table', IDUtil.cssClassName('metadata-table')];
        return (
            <div className={IDUtil.cssClassName('quick-entity-viewer')}>
                <table className={classNames.join(' ')}>
                    <tbody>
                        {searchButton}
                        {personImage}
                        {sourceLinks}
                    </tbody>
                </table>
            </div>
        );
    }
}

QuickEntityViewer.propTypes = {
    entityID : PropTypes.string.isRequired,
    entityType : PropTypes.string.isRequired,
    collectionConfig : PropTypes.object.isRequired,
    fieldCategories: PropTypes.array.isRequired, //which field clusters/categories are selected
};
