// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.

package source

import (
_	"context"
_	"encoding/json"
_	"fmt"
_	"gopkg.in/yaml.v3"
	"net/url"
_	"path/filepath"
	"decl/internal/resource"
_	"os"
_	"io"
	"strings"
	"log/slog"
)

type Iptable struct {
	Table string `yaml:"table" json:"table"`
	Chain string `yaml:"chain" json:"chain"`
}

func NewIptable() *Iptable {
	return &Iptable{}
}

func init() {
	SourceTypes.Register([]string{"iptable"}, func(u *url.URL) DocSource {
		t := NewIptable()
		t.Table = u.Hostname()
		t.Chain = strings.Split(u.RequestURI(), "/")[1]
		slog.Info("iptable chain source factory", "table", t, "uri", u, "table", u.Hostname()) 
		return t
	})

}


func (i *Iptable) Type() string { return "iptable" }

func (i *Iptable) ExtractResources(filter ResourceSelector) ([]*resource.Document, error) {
	documents := make([]*resource.Document, 0, 100)

	slog.Info("iptable chain source ExtractResources()", "table", i) 
	iptRules := make([]*resource.Iptable, 0, 100)
	cmd := resource.NewIptableReadChainCommand()
	if out, err := cmd.Execute(i); err == nil {
		slog.Info("iptable chain source ExtractResources()", "output", out)
		if exErr := cmd.Extractor(out, &iptRules); exErr != nil {
			return documents, exErr
		}
		for _, rule := range iptRules {
			document := resource.NewDocument()
			if rule == nil {
				rule = resource.NewIptable()
			}
			rule.Table = resource.IptableName(i.Table)
			rule.Chain = resource.IptableChain(i.Chain)
		
			document.AddResourceDeclaration("iptable", rule)
			documents = append(documents, document)
		}
	} else {
		slog.Info("iptable chain source ExtractResources()", "output", out, "error", err)
		return documents, err
	}
	return documents, nil
}
