"use strict";
/*
 * Copyright 2019 Unbounded Systems, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = tslib_1.__importStar(require("@adpt/core"));
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const Container_1 = require("../Container");
const docker_1 = require("../docker");
const NetworkService_1 = require("../NetworkService");
const Container_2 = require("./Container");
const Deployment_1 = require("./Deployment");
const Pod_1 = require("./Pod");
const Service_1 = require("./Service");
function mapChild(kid, props, helpers) {
    if (Container_1.isContainerElement(kid))
        return mapContainer(kid, props, helpers);
    if (NetworkService_1.isNetworkServiceElement(kid))
        return mapNetworkService(kid, props, helpers);
    return kid;
}
function mapContainer(absEl, props, helpers) {
    const { config, containerProps: rawContainerProps = {}, podProps = {}, 
    // tslint:disable-next-line: variable-name
    component: MyComponent, componentProps } = props;
    //just in case image is there anyway, remove it since Container will use it if present
    const _a = rawContainerProps, { image: _i } = _a, containerProps = tslib_1.__rest(_a, ["image"]);
    const _b = absEl.props, { handle: _h } = _b, absProps = tslib_1.__rest(_b, ["handle"]);
    let registryImage;
    let image = absProps.image;
    if (config.registryUrl !== undefined) {
        //FIXME(manishv) when RegistryDockerImage can push arbitrary string images, remove this
        if (!lodash_1.default.isString(image)) {
            const regImg = core_1.handle();
            registryImage = core_1.default.createElement(docker_1.RegistryDockerImage, { handle: regImg, registryUrl: config.registryUrl, imageSrc: image });
            image = regImg;
        }
        else {
            //FIXME(manishv) when helpers gives a way to warn, warn that string images aren't supported
        }
    }
    const elem = core_1.default.createElement(MyComponent, Object.assign({}, Object.assign({ config }, componentProps)),
        core_1.default.createElement(Pod_1.Pod, Object.assign({ isTemplate: true, key: absEl.props.key }, podProps),
            core_1.default.createElement(Container_2.Container, Object.assign({}, absProps, { image: image, k8sContainerProps: containerProps }))));
    absEl.props.handle.replaceTarget(elem, helpers);
    if (registryImage)
        return [registryImage, elem];
    return elem;
}
function mapNetworkService(absEl, props, helpers) {
    const { config, serviceProps = {} } = props;
    const hand = core_1.handle();
    const svc = core_1.default.createElement(Service_1.Service, Object.assign({ handle: hand, config: config, key: absEl.props.key }, Service_1.k8sServiceProps(absEl.props), serviceProps));
    absEl.props.handle.replaceTarget(svc, helpers);
    return svc;
}
/**
 * A component for mapping a group of abstract {@link Container}s and
 * {@link NetworkService}s to Kubernetes {@link k8s.Pod}s and
 * {@link k8s.K8sContainer}s.
 *
 * @remarks
 * This component is intended to be used to replace {@link Container} and
 * {@link NetworkService} components that are grouped together, as the
 * only children of a common parent in a pattern that looks like this:
 *
 * ```tsx
 * <Service>
 *   <Container ... />
 *   <Container ... />
 *   <NetworkService ... />
 * </Service>
 * ```
 *
 * `ServiceDeployment` would map those abstract components into corresponding
 * k8s components like this:
 * ```tsx
 * <Group>
 *   <docker.RegistryDockerImage ... /> //If props.config specifies a registry
 *   <k8s.Deployment ... >
 *     <Pod isTemplate>
 *       <k8s.K8sContainer ... />
 *     </Pod>
 *   </k8s.Deployment>
 *   <docker.RegistryDockerImage ... /> //If props.config specifies a registry
 *   <k8s.Deployment ... >
 *     <Pod isTemplate>
 *       <k8s.K8sContainer ... />
 *     </Pod>
 *   </k8s.Pod>
 *   <k8s.Service ... />
 * </Group>
 * ```
 * An example style rule to do this is:
 * ```tsx
 * {Adapt.rule((matchedProps) => {
 *     const { handle, ...remainingProps } = matchedProps;
 *     return <ServiceDeployment config={kubeconfig} {...remainingProps} />;
 * })}
 * ```
 * `ServiceDeployment` also requires the `config` prop which specifies
 * connection and authentication information for the Kubernetes cluster on
 * which these objects should be created.
 *
 * @public
 */
class ServiceDeployment extends core_1.DeferredComponent {
    build(helpers) {
        const mappedChildren = lodash_1.default.flatten(core_1.childrenToArray(this.props.children).map((c) => mapChild(c, this.props, helpers)));
        return core_1.default.createElement(core_1.Group, null, mappedChildren);
    }
}
ServiceDeployment.defaultProps = {
    component: Deployment_1.Deployment,
    componentProps: { replicas: 1 }
};
exports.ServiceDeployment = ServiceDeployment;
//# sourceMappingURL=ServiceDeployment.js.map