import { Language, LegalBasis } from '@signatu/common-lib';
import { Theme, WithStyles, withStyles } from '@signatu/styles';
import { ConsentActionType, ConsentConfig, ConsentEvent } from '@signatu/consent';
import { PolicyDataProcessing, TextContent } from '@signatu/policy';
import PropTypes from 'prop-types';
import React from 'react';

import { ConsentTitle } from '../lib/consentTitle';
import { DataProcessingConsent } from './dataProcessingConsent';

export interface DataProcessingGroupProps {
    config: ConsentConfig
    subject: string
    issuer: string
   
    delegate?: string

    groupId: string 
    type: ConsentActionType

    language?: string

    // Callbacks
    onAction?(consent: ConsentEvent): void
}

export interface DataProcessingGroupState {
    group?: any
}

const DEFAULT_DATAPROCESSING_API: string = "https://api.signatu.com/dataprocessing/v0"

const styles = (theme: Theme) => ({
    root: {
        marginTop: "2em", 
    }, 
    consentContainer: {
        marginBottom: "1.5em"
    }
})

class DataProcessingGroup extends React.Component<DataProcessingGroupProps & WithStyles, DataProcessingGroupState> {
    /** PropTypes for non-Typescript environments */
    static propTypes = {
        config: PropTypes.object.isRequired as PropTypes.Validator<ConsentConfig>, 
        subject: PropTypes.string.isRequired, 
        issuer: PropTypes.string.isRequired, 
        groupId: PropTypes.string.isRequired, 
        type: PropTypes.string as PropTypes.Validator< ConsentActionType>, 
        delegate: PropTypes.string as PropTypes.Validator<string | undefined>, 

        language: PropTypes.string as PropTypes.Validator<string | undefined>, 
        onAction: PropTypes.func as PropTypes.Validator<(consent: ConsentEvent) => any | undefined>, 

        classes: PropTypes.object as PropTypes.Validator<any>
    }

    state: DataProcessingGroupState = {}

    componentIsMounted = false

    private endPoint: string = ""

    async componentWillMount() {
        if (this.props.groupId) {
            this.loadGroup(this.props.groupId)
        }
    }
    async componentWillReceiveProps(newProps: DataProcessingGroupProps) {
        if (newProps.groupId !== this.props.groupId) {
            this.loadGroup(newProps.groupId)
        }
    }

    componentDidMount() {
        this.componentIsMounted = true
    }
    componentWillUnmount() {
        this.componentIsMounted = false
    }

    async loadGroup(groupId: string) {
        const base = this.props.config && this.props.config.dataprocessingAPI || DEFAULT_DATAPROCESSING_API
        this.endPoint = base.replace(/\/*$/, "") + `/dpgroups/${groupId}`

        /** Fetch the data processing */
        const response = await fetch(this.endPoint, {
            method: 'GET', 
            headers: {
                Authorization: `Bearer ${this.props.config.accessToken}`
            }
        })
        const group = await response.json()
        if ( ! ( group && group.specs ) ) {
            return
        }
        /** Make the specs PolicyDataProcessing objects */
        group.specs = group.specs.map((s: any) => {
            const dp = new PolicyDataProcessing(s.action, s.data, s.purpose, s.location, s.sensitive, s.consentTarget, s.legalBasis);
            /** This will be used as the scope */
            dp.elementId = s.id;
            /** Add all texts as content */
            (s.texts || []).forEach((t: any) => dp.addContent(new TextContent(t.value, new Language(t.language))))
            return dp
        })
        if (this.componentIsMounted) {
            this.setState({group})
        }
    }

    render() {
        const { config, subject, issuer, type, delegate, classes, language } = this.props
        const {group} = this.state

        if (!group) {
            return <div data-type="DataProcessingGroup">No group: {this.props.groupId}</div>
        }
        return (
        <div className={classes.root} data-type="DataProcessingGroup">
            <ConsentTitle
                title={group.name}
                subtitle={<div>
                    {group.description}
                </div>}
            />
            {group.specs.map((s: PolicyDataProcessing, idx: number) => <div className={classes.consentContainer} key={idx}>
                <DataProcessingConsent
                    /** Set all common props */
                    config={config}
                    subject={subject}
                    issuer={issuer}
                    delegate={delegate}
                    type={type}
                    language={language}

                    /** Overrides */
                    scope={s.elementId}
                    target={this.endPoint}
                    source={document.location && document.location.href || undefined}
                    title={undefined}
                    subtitle={undefined}
                    optOut={s.legalBasis === LegalBasis.LEGITIMATE_INTEREST}
                    dataprocessing={s}
                />
            </div>
            )}
        </div> 
        )
    }
}

const styled = withStyles<DataProcessingGroupProps>(styles)(DataProcessingGroup)
export { styled as DataProcessingGroup }
