package models

import (
	"time"
)

var offensiveSecurityDateFormat = "2006-01-02"

// ExploitType :
type ExploitType string

var (
	// OffensiveSecurityType : https://www.exploit-db.com/
	OffensiveSecurityType ExploitType = "OffensiveSecurity"
)

// Exploit :
type Exploit struct {
	ID                int64              `json:",omitempty"`
	ExploitType       ExploitType        `json:"exploit_type"`
	ExploitUniqueID   string             `json:"exploit_unique_id"`
	URL               string             `json:"url"`
	Description       string             `json:"description"`
	CveID             string             `json:"cve_id"`
	OffensiveSecurity *OffensiveSecurity `json:"offensive_security"`
}

// OffensiveSecurity : https://www.exploit-db.com/
type OffensiveSecurity struct {
	ID              int64      `json:",omitempty"`
	ExploitID       int64      `sql:"type:bigint REFERENCES exploits(id)" json:",omitempty"`
	ExploitUniqueID string     `json:"exploit_unique_id"`
	Document        *Document  `json:"document"`
	ShellCode       *ShellCode `json:"shell_code"`
	Paper           *Paper     `json:"paper"`
}

// Document :
// https://github.com/offensive-security/exploitdb/tree/master/exploits
type Document struct {
	OffensiveSecurityID int64                 `sql:"type:bigint REFERENCES offensive_securities(id)" json:",omitempty"`
	ExploitUniqueID     string                `csv:"id" json:"exploit_unique_id"`
	DocumentURL         string                `csv:"file" json:"document_url"`
	Description         string                `csv:"description" json:"description"`
	Date                OffensiveSecurityTime `csv:"date" json:"date"`
	Author              string                `csv:"author" json:"author"`
	// docs local remote webapps
	Type     string `csv:"type" json:"type"`
	Platform string `csv:"platform" json:"palatform"`
	Port     string `csv:"port" json:"port"`
}

// ShellCode :
// https://github.com/offensive-security/exploitdb/tree/master/shellcodes
type ShellCode struct {
	OffensiveSecurityID int64                 `sql:"type:bigint REFERENCES offensive_securities(id)" json:",omitempty"`
	ExploitUniqueID     string                `csv:"id" json:"exploit_unique_id"`
	ShellCodeURL        string                `csv:"file" json:"shell_code_url"`
	Description         string                `csv:"description" json:"description"`
	Date                OffensiveSecurityTime `csv:"date" json:"date"`
	Author              string                `csv:"author" json:"author"`
	Platform            string                `csv:"platform" json:"platform"`
}

// Paper :
// https://github.com/offensive-security/exploitdb-papers
type Paper struct {
	OffensiveSecurityID int64                 `sql:"type:bigint REFERENCES offensive_securities(id)" json:",omitempty"`
	ExploitUniqueID     string                `csv:"id" json:"exploit_unique_id"`
	PaperURL            string                `csv:"file" json:"paper_url"`
	Description         string                `csv:"description" json:"description"`
	Date                OffensiveSecurityTime `csv:"date" json:"date"`
	Author              string                `csv:"author" json:"author"`
	Platform            string                `csv:"platform" json:"platform"`
	Language            string                `csv:"language" json:"language"`
}

// MitreXML :
// http://cve.mitre.org/cve/cvrf.html
type MitreXML struct {
	Vulnerability []struct {
		CVE        string `xml:"CVE"`
		References []struct {
			// External, Self
			AttrType    string `xml:"Type,attr"`
			URL         string `xml:"URL"`
			Description string `xml:"Description"`
		} `xml:"References>Reference"`
	} `xml:"Vulnerability"`
}

// GithubJSON :
type GithubJSON struct {
	TotalCount int `json:"total_count"`
	Items      []struct {
		Name string `json:"name"`
		Path string `json:"path"`
	} `json:"items"`
}

// OffensiveSecurityTime :
type OffensiveSecurityTime struct {
	time.Time
}

// String :
// You could also use the standard Stringer interface
func (date *OffensiveSecurityTime) String() string {
	return date.String() // Redundant, just for example
}

// UnmarshalCSV :
// Convert the CSV string as internal date
func (date *OffensiveSecurityTime) UnmarshalCSV(csv string) (err error) {
	date.Time, err = time.Parse(offensiveSecurityDateFormat, csv)
	if err != nil {
		return err
	}
	return nil
}
