// package use_case -- вариант использования
package use_case

import (
	"fmt"

	"gitp78su.ipnodns.ru/svi/test_arch/lev0/alias"
	"gitp78su.ipnodns.ru/svi/test_arch/lev0/cons"
	"gitp78su.ipnodns.ru/svi/test_arch/lev0/types"
	"gitp78su.ipnodns.ru/svi/test_arch/pkg/elems/elem_base"
	"gitp78su.ipnodns.ru/svi/test_arch/pkg/elems/size"
)

// UseCase -- вариант использования
type UseCase struct {
	*elem_base.ElemBase
	*size.Size
	Links_ []alias.Id `json:"links"` // Список ссылок
}

// NewUseCase -- возвращает новый вариант использования
func NewUseCase(elem map[string]interface{}) (*UseCase, error) {
	elemBase, err := elem_base.NewElemBase(elem)
	if err != nil {
		return nil, fmt.Errorf("NewUseCase(): in create BaseSvg, err=\n\t%w", err)
	}
	id := elemBase.Id_
	_links0, isOk := elemBase.Elem_["links"]
	if !isOk {
		return nil, fmt.Errorf("NewUseCase(): id=%q, field `links` not found<br>%+v", id, elemBase.StrElem_)
	}
	_links, isOk := _links0.([]interface{})
	if !isOk {
		return nil, fmt.Errorf("NewUseCase(): id=%q, `links`(%+v) not []interface{}", id, _links0)
	}
	var links []alias.Id
	for _, _id := range _links {
		id0, isOk := _id.(string)
		if !isOk {
			return nil, fmt.Errorf("NewUseCase(): id=%q, `link`(%T, %+v) not string", id, _id, _id)
		}
		id1 := alias.Id(id0)
		if id1 == "" {
			return nil, fmt.Errorf("NewUseCase(): id=%q, `link` is empty", id)
		}
		links = append(links, id1)
	}
	sf := &UseCase{
		ElemBase: elemBase,
		Size:     size.NewSize("size", elem),
		Links_:   links,
	}
	return sf, nil
}

// Check -- проверяет корректность элемента
func (sf *UseCase) Check(mapElem map[alias.Id]types.IElemDrawer) string {
	var msgErr string
	// Нет ссылок
	if len(sf.Links_) == 0 {
		return fmt.Sprintf("id=%q, нет собственных ссылок", sf.Id_)
	}
	// Проверить, что ссылки реально существует
	for _, id := range sf.Links_ {
		link, ok := mapElem[id]
		if !ok {
			msgErr += fmt.Sprintf("id=%q, собственная ссылка не существует\n", id)
			continue
		}
		if link.Type() != cons.TypeUseLink {
			msgErr += fmt.Sprintf("id=%q, не тип %q, тип=%q\n", id, cons.TypeUseLink, link.Type())
			continue
		}
		ln, isOk := link.(types.ILinker)
		if !isOk {
			msgErr += fmt.Sprintf("id=%q, не тип `link`, link=%#v\n", id, link)
			continue
		}
		// Проверить что ссылка взаимная
		if !(ln.SrcId() == sf.Id_ || ln.DstId() == sf.Id_) {
			msgErr += fmt.Sprintf("id=%q, ссылка не взаимная\nsrc=%q, dst=%q\n", id, ln.SrcId(), ln.DstId())
		}
	}
	return msgErr
}

// Links -- ссылки вариантов использования
func (sf *UseCase) Links() []alias.Id {
	return sf.Links_
}
