// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package xcoff

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

const (
	SAIAMAG   = 0x8
	AIAFMAG   = "`\n"
	AIAMAG    = "<aiaff>\n"
	AIAMAGBIG = "<bigaf>\n"

	// Sizeof
	FL_HSZ_BIG = 0x80
	AR_HSZ_BIG = 0x70
)

type bigarFileHeader struct {
	Flmagic    [SAIAMAG]byte // Archive magic string
	Flmemoff   [20]byte      // Member table offset
	Flgstoff   [20]byte      // 32-bits global symtab offset
	Flgst64off [20]byte      // 64-bits global symtab offset
	Flfstmoff  [20]byte      // First member offset
	Fllstmoff  [20]byte      // Last member offset
	Flfreeoff  [20]byte      // First member on free list offset
}

type bigarMemberHeader struct {
	Arsize   [20]byte // File member size
	Arnxtmem [20]byte // Next member pointer
	Arprvmem [20]byte // Previous member pointer
	Ardate   [12]byte // File member date
	Aruid    [12]byte // File member uid
	Argid    [12]byte // File member gid
	Armode   [12]byte // File member mode (octal)
	Arnamlen [4]byte  // File member name length
	// _ar_nam is removed because it's easier to get name without it.
}

// Archive represents an open AIX big archive.
type Archive struct {
	ArchiveHeader
	Members []*Member

	closer io.Closer
}

// MemberHeader holds information about a big archive file header
type ArchiveHeader struct {
	magic string
}

// Member represents a member of an AIX big archive.
type Member struct {
	MemberHeader
	sr *io.SectionReader
}

// MemberHeader holds information about a big archive member
type MemberHeader struct {
	Name string
	Size uint64
}

// OpenArchive opens the named archive using os.Open and prepares it for use
// as an AIX big archive.
func OpenArchive(name string) (*Archive, error) {
	f, err := os.Open(name)
	if err != nil {
		return nil, err
	}
	arch, err := NewArchive(f)
	if err != nil {
		f.Close()
		return nil, err
	}
	arch.closer = f
	return arch, nil
}

// Close closes the Archive.
// If the Archive was created using NewArchive directly instead of OpenArchive,
// Close has no effect.
func (a *Archive) Close() error {
	var err error
	if a.closer != nil {
		err = a.closer.Close()
		a.closer = nil
	}
	return err
}

// NewArchive creates a new Archive for accessing an AIX big archive in an underlying reader.
func NewArchive(r io.ReaderAt) (*Archive, error) {
	parseDecimalBytes := func(b []byte) (int64, error) {
		return strconv.ParseInt(strings.TrimSpace(string(b)), 10, 64)
	}
	sr := io.NewSectionReader(r, 0, 1<<63-1)

	// Read File Header
	var magic [SAIAMAG]byte
	if _, err := sr.ReadAt(magic[:], 0); err != nil {
		return nil, err
	}

	arch := new(Archive)
	switch string(magic[:]) {
	case AIAMAGBIG:
		arch.magic = string(magic[:])
	case AIAMAG:
		return nil, fmt.Errorf("small AIX archive not supported")
	default:
		return nil, fmt.Errorf("unrecognised archive magic: 0x%x", magic)
	}

	var fhdr bigarFileHeader
	if _, err := sr.Seek(0, os.SEEK_SET); err != nil {
		return nil, err
	}
	if err := binary.Read(sr, binary.BigEndian, &fhdr); err != nil {
		return nil, err
	}

	off, err := parseDecimalBytes(fhdr.Flfstmoff[:])
	if err != nil {
		return nil, fmt.Errorf("error parsing offset of first member in archive header(%q); %v", fhdr, err)
	}

	if off == 0 {
		// Occurs if the archive is empty.
		return arch, nil
	}

	lastoff, err := parseDecimalBytes(fhdr.Fllstmoff[:])
	if err != nil {
		return nil, fmt.Errorf("error parsing offset of first member in archive header(%q); %v", fhdr, err)
	}

	// Read members
	for {
		// Read Member Header
		// The member header is normally 2 bytes larger. But it's easier
		// to read the name if the header is read without _ar_nam.
		// However, AIAFMAG must be read afterward.
		if _, err := sr.Seek(off, os.SEEK_SET); err != nil {
			return nil, err
		}

		var mhdr bigarMemberHeader
		if err := binary.Read(sr, binary.BigEndian, &mhdr); err != nil {
			return nil, err
		}

		member := new(Member)
		arch.Members = append(arch.Members, member)

		size, err := parseDecimalBytes(mhdr.Arsize[:])
		if err != nil {
			return nil, fmt.Errorf("error parsing size in member header(%q); %v", mhdr, err)
		}
		member.Size = uint64(size)

		// Read name
		namlen, err := parseDecimalBytes(mhdr.Arnamlen[:])
		if err != nil {
			return nil, fmt.Errorf("error parsing name length in member header(%q); %v", mhdr, err)
		}
		name := make([]byte, namlen)
		if err := binary.Read(sr, binary.BigEndian, name); err != nil {
			return nil, err
		}
		member.Name = string(name)

		fileoff := off + AR_HSZ_BIG + namlen
		if fileoff&1 != 0 {
			fileoff++
			if _, err := sr.Seek(1, os.SEEK_CUR); err != nil {
				return nil, err
			}
		}

		// Read AIAFMAG string
		var fmag [2]byte
		if err := binary.Read(sr, binary.BigEndian, &fmag); err != nil {
			return nil, err
		}
		if string(fmag[:]) != AIAFMAG {
			return nil, fmt.Errorf("AIAFMAG not found after member header")
		}

		fileoff += 2 // Add the two bytes of AIAFMAG
		member.sr = io.NewSectionReader(sr, fileoff, size)

		if off == lastoff {
			break
		}
		off, err = parseDecimalBytes(mhdr.Arnxtmem[:])
		if err != nil {
			return nil, fmt.Errorf("error parsing offset of first member in archive header(%q); %v", fhdr, err)
		}

	}

	return arch, nil

}

// GetFile returns the XCOFF file defined by member name.
// FIXME: This doesn't work if an archive has two members with the same
// name which can occur if a archive has both 32-bits and 64-bits files.
func (arch *Archive) GetFile(name string) (*File, error) {
	for _, mem := range arch.Members {
		if mem.Name == name {
			return NewFile(mem.sr)
		}
	}
	return nil, fmt.Errorf("unknown member %s in archive", name)

}
