/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.
*/

package integration

import (
	"context"
	"fmt"
	"path"

	"github.com/pkg/errors"

	"github.com/apache/camel-k/pkg/util/digest"

	"github.com/apache/camel-k/pkg/trait"

	"github.com/apache/camel-k/pkg/builder"
	"github.com/operator-framework/operator-sdk/pkg/sdk"
	"github.com/sirupsen/logrus"

	"github.com/apache/camel-k/pkg/platform"

	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
)

// NewBuildImageAction create an action that handles integration image build
func NewBuildImageAction(ctx context.Context, namespace string) Action {
	return &buildImageAction{
		Context:   ctx,
		namespace: namespace,
	}
}

type buildImageAction struct {
	context.Context
	namespace string
}

func (action *buildImageAction) Name() string {
	return "build-image"
}

func (action *buildImageAction) CanHandle(integration *v1alpha1.Integration) bool {
	return integration.Status.Phase == v1alpha1.IntegrationPhaseBuildingImage
}

func (action *buildImageAction) Handle(integration *v1alpha1.Integration) error {

	// in this phase the integration need to be associated to a context whose image
	// will be used as base image for the integration images
	if integration.Spec.Context == "" {
		return fmt.Errorf("context is not set for integration: %s", integration.Name)
	}

	// look-up the integration context associated to this integration, this is needed
	// to determine the base image
	ctx := v1alpha1.NewIntegrationContext(integration.Namespace, integration.Spec.Context)
	if err := sdk.Get(&ctx); err != nil {
		return errors.Wrapf(err, "unable to find integration context %s, %s", ctx.Name, err)
	}

	b, err := platform.GetPlatformBuilder(action.Context, action.namespace)
	if err != nil {
		return err
	}
	env, err := trait.Apply(integration, &ctx)
	if err != nil {
		return err
	}

	// This build do not require to determine dependencies nor a project, the builder
	// step do remove them
	r := builder.Request{
		Meta:     integration.ObjectMeta,
		Steps:    env.Steps,
		BuildDir: env.BuildDir,
		Platform: env.Platform.Spec,
		Image:    ctx.Status.Image,
	}

	// Sources are added as part of the standard deployment bits
	r.Resources = make([]builder.Resource, 0, len(integration.Spec.Sources))

	for _, source := range integration.Spec.Sources {
		r.Resources = append(r.Resources, builder.Resource{
			Content: []byte(source.Content),
			Target:  path.Join("sources", source.Name),
		})
	}

	res := b.Submit(r)

	switch res.Status {
	case builder.StatusSubmitted:
		logrus.Info("Build submitted")
	case builder.StatusStarted:
		logrus.Info("Build started")
	case builder.StatusError:
		target := integration.DeepCopy()
		target.Status.Phase = v1alpha1.IntegrationPhaseError

		logrus.Infof("Integration %s transitioning to state %s, reason: %s", target.Name, target.Status.Phase, res.Error.Error())

		// remove the build from cache
		defer b.Purge(r)

		return sdk.Update(target)
	case builder.StatusCompleted:
		target := integration.DeepCopy()
		target.Status.Phase = v1alpha1.IntegrationPhaseDeploying
		target.Status.Image = res.Image

		dgst, err := digest.ComputeForIntegration(integration)
		if err != nil {
			return err
		}

		target.Status.Digest = dgst

		logrus.Info("Integration ", target.Name, " transitioning to state ", target.Status.Phase)

		// remove the build from cache
		defer b.Purge(r)

		if err := sdk.Update(target); err != nil {
			return err
		}
	}

	return nil
}
