<commit_before>import {RecipeState, SceneSelectionType} from 'app/home/body/process/mosaic/mosaicRecipe'
import EarthEngineImageLayer from 'app/home/map/earthEngineLayer'
import {sepalMap} from 'app/home/map/map'
import backend from 'backend'
import _ from 'lodash'
import React from 'react'
import {connect} from 'store'
import {msg, Msg} from 'translate'
import Icon from 'widget/icon'
import MapStatus from 'widget/mapStatus'
import styles from './mosaicPreview.module.css'


const mapStateToProps = (state, ownProps) => {
    const recipeState = RecipeState(ownProps.recipeId)
    return {
        recipe: recipeState()
    }
}

class MosaicPreview extends React.Component {
    state = {}

    render() {
        const {initializing, tiles, error} = this.state
        if (this.isHidden())
            return null
        else if (error) {
            return (
                <MapStatus loading={false} error={error}/>
            )
        }
        else if (initializing)
            return (
                <MapStatus message={msg('process.mosaic.preview.initializing')}/>
            )
        else if (tiles && (!tiles.complete || tiles.failed))
            return (
                <MapStatus
                    loading={!tiles.complete}
                    message={msg('process.mosaic.preview.loading', {loaded: tiles.loaded, count: tiles.count})}
                    error={tiles.failed ? msg('process.mosaic.preview.tilesFailed', {failed: tiles.failed}) : error}/>
            )
        else
            return null
    }

    onProgress(tiles) {
        this.setState(prevState => ({...prevState, tiles, initializing: false}))
    }

    onError() {
        this.setState(prevState => ({
            ...prevState,
            error:
                <div>
                    <Msg id='process.mosaic.preview.error'/>
                    <div className={styles.retry}>
                        <a
                            href=''
                            onClick={(e) => {
                                e.preventDefault()
                                this.reload()
                            }}>
                            <Icon name='sync'/>
                            <Msg id='button.retry'/>
                        </a>
                    </div>

                </div>
        }))
    }

    reload() {
        const {recipeId} = this.props
        this.setState(prevState => ({...prevState, error: null}))
        sepalMap.getContext(recipeId).setLayer({id: 'preview', layer: null})
    }

    isPreviewShown() {
        const {recipe} = this.props
        return recipe.ui.initialized
            && !recipe.ui.autoSelectingScenes
            && recipe.bands
            && (recipe.sceneSelectionOptions.type === SceneSelectionType.ALL
                || (recipe.scenes && Object.keys(recipe.scenes).find(sceneAreaId => recipe.scenes[sceneAreaId].length > 0)))
    }


    toLayerProps(recipe) {
        return _.omit(recipe, ['ui', 'placeholder', 'title'])
    }

    componentDidUpdate(prevProps) {
        const {recipe} = this.props
        const layerProps = this.toLayerProps(recipe)
        const layerChanged = !_.isEqual(layerProps, this.toLayerProps(prevProps.recipe))
        if (layerChanged)
            this.updateLayer()
        const context = sepalMap.getContext(recipe.id)
        context.hideLayer('preview', this.isHidden(recipe))
    }

    updateLayer() {
        const {recipe, componentWillUnmount$} = this.props
        const {initializing, error} = this.state
        const layer = this.isPreviewShown()
            ? new EarthEngineImageLayer({
                layerIndex: 0,
                bounds: recipe.ui.aoi.bounds,
                mapId$: backend.gee.preview$(recipe),<commit_msg>Updated layer when mosaic preview mounts.<commit_after>import {RecipeState, SceneSelectionType} from 'app/home/body/process/mosaic/mosaicRecipe'
import EarthEngineImageLayer from 'app/home/map/earthEngineLayer'
import {sepalMap} from 'app/home/map/map'
import backend from 'backend'
import _ from 'lodash'
import React from 'react'
import {connect} from 'store'
import {msg, Msg} from 'translate'
import Icon from 'widget/icon'
import MapStatus from 'widget/mapStatus'
import styles from './mosaicPreview.module.css'


const mapStateToProps = (state, ownProps) => {
    const recipeState = RecipeState(ownProps.recipeId)
    return {
        recipe: recipeState()
    }
}

class MosaicPreview extends React.Component {
    state = {}

    render() {
        const {initializing, tiles, error} = this.state
        if (this.isHidden())
            return null
        else if (error) {
            return (
                <MapStatus loading={false} error={error}/>
            )
        }
        else if (initializing)
            return (
                <MapStatus message={msg('process.mosaic.preview.initializing')}/>
            )
        else if (tiles && (!tiles.complete || tiles.failed))
            return (
                <MapStatus
                    loading={!tiles.complete}
                    message={msg('process.mosaic.preview.loading', {loaded: tiles.loaded, count: tiles.count})}
                    error={tiles.failed ? msg('process.mosaic.preview.tilesFailed', {failed: tiles.failed}) : error}/>
            )
        else
            return null
    }

    onProgress(tiles) {
        this.setState(prevState => ({...prevState, tiles, initializing: false}))
    }

    onError() {
        this.setState(prevState => ({
            ...prevState,
            error:
                <div>
                    <Msg id='process.mosaic.preview.error'/>
                    <div className={styles.retry}>
                        <a
                            href=''
                            onClick={(e) => {
                                e.preventDefault()
                                this.reload()
                            }}>
                            <Icon name='sync'/>
                            <Msg id='button.retry'/>
                        </a>
                    </div>

                </div>
        }))
    }

    reload() {
        const {recipeId} = this.props
        this.setState(prevState => ({...prevState, error: null}))
        sepalMap.getContext(recipeId).setLayer({id: 'preview', layer: null})
    }

    isPreviewShown() {
        const {recipe} = this.props
        return recipe.ui.initialized
            && !recipe.ui.autoSelectingScenes
            && recipe.bands
            && (recipe.sceneSelectionOptions.type === SceneSelectionType.ALL
                || (recipe.scenes && Object.keys(recipe.scenes).find(sceneAreaId => recipe.scenes[sceneAreaId].length > 0)))
    }


    toLayerProps(recipe) {
        return _.omit(recipe, ['ui', 'placeholder', 'title'])
    }

    componentDidMount() {
        this.updateLayer()
    }

    componentDidUpdate(prevProps) {
        const {recipe} = this.props
        const layerProps = this.toLayerProps(recipe)
        const layerChanged = !_.isEqual(layerProps, this.toLayerProps(prevProps.recipe))
        if (layerChanged)
            this.updateLayer()
        const context = sepalMap.getContext(recipe.id)
        context.hideLayer('preview', this.isHidden(recipe))
    }

    updateLayer() {
        const {recipe, componentWillUnmount$} = this.props
        const {initializing, error} = this.state
        const layer = this.isPreviewShown()
            ? new EarthEngineImageLayer({
                layerIndex: 0,
                bounds: recipe.ui.aoi.bounds,
                mapId$: backend.gee.preview$(recipe),
{'fraction_non_alphanumeric': 0.12038988408851423, 'fraction_numerical': 0.0005268703898840885, 'mean_word_length': 1.7600872410032715, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1375880', 'n_tokens_mistral': 2119, 'n_tokens_neox': 2042, 'n_words': 410}