/**
 * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
 *
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @author Ludovic Autin <ludovic.autin@gmail.com>
 */

import { StateObjectRef } from '../../mol-state';
import { StructureRepresentationPresetProvider, presetStaticComponent } from '../../mol-plugin-state/builder/structure/representation-preset';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { ColorNames } from '../../mol-util/color/names';
import { CellPackGenerateColorThemeProvider } from './color/generate';

export const CellpackPackingPresetParams = {
    traceOnly: PD.Boolean(true),
    ignoreLight: PD.Boolean(false),
    representation: PD.Select('gaussian-surface', PD.arrayToOptions(['gaussian-surface', 'spacefill', 'point', 'orientation'] as const)),
};
export type CellpackPackingPresetParams = PD.ValuesFor<typeof CellpackPackingPresetParams>

export const CellpackPackingPreset = StructureRepresentationPresetProvider({
    id: 'preset-structure-representation-cellpack-packing',
    display: { name: 'CellPack Packing' },
    params: () => CellpackPackingPresetParams,
    async apply(ref, params, plugin) {
        const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
        if (!structureCell) return {};

        const reprProps = {
            ignoreHydrogens: true,
            traceOnly: params.traceOnly,
            instanceGranularity: true,
            ignoreLight: params.ignoreLight,
        };
        const components = {
            polymer: await presetStaticComponent(plugin, structureCell, 'polymer')
        };

        if (params.representation === 'gaussian-surface') {
            Object.assign(reprProps, {
                quality: 'custom', resolution: 10, radiusOffset: 2, doubleSided: false
            });
        } else if (params.representation === 'spacefill') {
            Object.assign(reprProps, { sizeFactor: params.traceOnly ? 2 : 1 });
        }

        // default is generated
        const color = CellPackGenerateColorThemeProvider.name;

        const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, {});
        const representations = {
            polymer: builder.buildRepresentation<any>(update, components.polymer, { type: params.representation, typeParams: { ...typeParams, ...reprProps }, color }, { tag: 'polymer' })
        };

        await update.commit({ revertOnError: true });
        return { components, representations };
    }
});

//

export const CellpackMembranePresetParams = {
    ignoreLight: PD.Boolean(false),
    representation: PD.Select('gaussian-surface', PD.arrayToOptions(['gaussian-surface', 'spacefill', 'point', 'orientation'] as const)),
};
export type CellpackMembranePresetParams = PD.ValuesFor<typeof CellpackMembranePresetParams>

export const CellpackMembranePreset = StructureRepresentationPresetProvider({
    id: 'preset-structure-representation-cellpack-membrane',
    display: { name: 'CellPack Membrane' },
    params: () => CellpackMembranePresetParams,
    async apply(ref, params, plugin) {
        const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
        if (!structureCell) return {};

        const reprProps = {
            ignoreHydrogens: true,
            instanceGranularity: true,
            ignoreLight: params.ignoreLight,
        };
        const components = {
            membrane: await presetStaticComponent(plugin, structureCell, 'all', { label: 'Membrane' })
        };

        if (params.representation === 'gaussian-surface') {
            Object.assign(reprProps, {
                quality: 'custom', resolution: 10, radiusOffset: 2, doubleSided: false
            });
        }

        const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, {});
        const representations = {
            membrane: builder.buildRepresentation(update, components.membrane, { type: params.representation, typeParams: { ...typeParams, ...reprProps }, color: 'uniform', colorParams: { value: ColorNames.lightgrey } }, { tag: 'all' })
        };

        await update.commit({ revertOnError: true });

        return { components, representations };
    }
});
