package toproto

import (
	"errors"

	"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5"
	"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
)

var ErrUnknownAttributePathStepType = errors.New("unknown type of AttributePath_Step")

func AttributePath(in *tftypes.AttributePath) (*tfplugin5.AttributePath, error) {
	steps, err := AttributePath_Steps(in.Steps)
	if err != nil {
		return nil, err
	}
	return &tfplugin5.AttributePath{
		Steps: steps,
	}, nil
}

func AttributePaths(in []*tftypes.AttributePath) ([]*tfplugin5.AttributePath, error) {
	resp := make([]*tfplugin5.AttributePath, 0, len(in))
	for _, a := range in {
		if a == nil {
			resp = append(resp, nil)
			continue
		}
		attr, err := AttributePath(a)
		if err != nil {
			return resp, err
		}
		resp = append(resp, attr)
	}
	return resp, nil
}

func AttributePath_Step(step tftypes.AttributePathStep) (*tfplugin5.AttributePath_Step, error) {
	var resp tfplugin5.AttributePath_Step
	if name, ok := step.(tftypes.AttributeName); ok {
		resp.Selector = &tfplugin5.AttributePath_Step_AttributeName{
			AttributeName: string(name),
		}
		return &resp, nil
	}
	if key, ok := step.(tftypes.ElementKeyString); ok {
		resp.Selector = &tfplugin5.AttributePath_Step_ElementKeyString{
			ElementKeyString: string(key),
		}
		return &resp, nil
	}
	if key, ok := step.(tftypes.ElementKeyInt); ok {
		resp.Selector = &tfplugin5.AttributePath_Step_ElementKeyInt{
			ElementKeyInt: int64(key),
		}
		return &resp, nil
	}
	if _, ok := step.(tftypes.ElementKeyValue); ok {
		// the protocol has no equivalent of an ElementKeyValue, so we
		// return nil for both the step and the error here, to signal
		// that we've hit a step we can't convey back to Terraform
		return nil, nil
	}
	return nil, ErrUnknownAttributePathStepType
}

func AttributePath_Steps(in []tftypes.AttributePathStep) ([]*tfplugin5.AttributePath_Step, error) {
	resp := make([]*tfplugin5.AttributePath_Step, 0, len(in))
	for _, step := range in {
		if step == nil {
			resp = append(resp, nil)
			continue
		}
		s, err := AttributePath_Step(step)
		if err != nil {
			return resp, err
		}
		// in the face of a set, the protocol has no way to represent
		// the index, so we just bail and return the prefix we can
		// return.
		if s == nil {
			return resp, nil
		}
		resp = append(resp, s)
	}
	return resp, nil
}

// we have to say this next thing to get golint to stop yelling at us about the
// underscores in the function names. We want the function names to match
// actually-generated code, so it feels like fair play. It's just a shame we
// lose golint for the entire file.
//
// This file is not actually generated. You can edit it. Ignore this next line.
// Code generated by hand ignore this next bit DO NOT EDIT.
