<commit_before>package mater

import (
	"bytes"
	"encoding/json"
	"github.com/teomat/mater/collision"
	"github.com/teomat/mater/transform"
	"log"
	"os"
)

var saveDirectory = "saves/"

func (mater *Mater) SaveScene(path string) error {
	scene := mater.Scene

	path = saveDirectory + path

	file, err := os.Create(path)
	if err != nil {
		log.Printf("Error opening File: %v", err)
		return err
	}
	defer file.Close()

	//encoder := json.NewEncoder(file)
	//err = encoder.Encode(scene)

	dataString, err := json.MarshalIndent(scene, "", "\t")
	if err != nil {
		log.Printf("Error encoding Scene: %v", err)
		return err
	}

	buf := bytes.NewBuffer(dataString)
	n, err := buf.WriteTo(file)
	if err != nil {
		log.Printf("Error after writing %v characters to File: %v", n, err)
		return err
	}

	return nil
}

func (mater *Mater) LoadScene(path string) error {

	var scene *Scene

	path = saveDirectory + path

	file, err := os.Open(path)
	if err != nil {
		log.Printf("Error opening File: %v", err)
		return err
	}
	defer file.Close()

	scene = new(Scene)
	cam := mater.DefaultCamera
	scene.Camera = &cam
	decoder := json.NewDecoder(file)

	err = decoder.Decode(scene)
	if err != nil {
		log.Printf("Error decoding Scene: %v", err)
		return err
	}

	mater.Scene.Destroy()

	mater.Scene = scene
	scene.Space.Enabled = true

	if mater.Scene.Camera == nil {
		cam := mater.DefaultCamera
		mater.Scene.Camera = &cam
	} else {
		mater.Scene.Camera.ScreenSize = mater.ScreenSize
	}

	mater.Dbg.DebugView.Reset(mater.Scene.Space)

	return nil
}

func (scene *Scene) MarshalJSON() ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	encoder := json.NewEncoder(buf)

	var err error

	buf.WriteString(`{"Camera":`)
	encoder.Encode(scene.Camera)

	buf.WriteString(`,"StaticEntity":`)
	encoder.Encode(&scene.StaticEntity)

	buf.WriteString(`,"Entities":`)
	entities, err := scene.MarshalEntities()
	if err != nil {
		return nil, err
	}
	buf.Write(entities)

	buf.WriteString(`,"Space":`)
	err = encoder.Encode(scene.Space)
	if err != nil {
		log.Printf("Error encoding scene")
		return nil, err
	}

	buf.WriteByte('}')

	return buf.Bytes(), nil
}

func (scene *Scene) MarshalEntities() ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	encoder := json.NewEncoder(buf)

	buf.WriteByte('[')
	for _, entity := range scene.Entities {

		err := encoder.Encode(entity)
		if err != nil {
			log.Printf("Error encoding entity")
			return nil, err
		}

		buf.WriteByte(',')
	}
	if len(scene.Entities) > 0 {
		//cut trailing comma
		buf.Truncate(buf.Len() - 1)
	}

	buf.WriteByte(']')

	return buf.Bytes(), nil
}

func (scene *Scene) UnmarshalJSON(data []byte) error {
	sceneData := struct {
		Camera       *Camera
		Space        *collision.Space
		StaticEntity json.RawMessage
		Entities     []json.RawMessage
	}{}

	err := json.Unmarshal(data, &sceneData)
	if err != nil {
		log.Printf("Error decoding scene")
		return err
	}

	sd := &sceneData

	staticEntity, err := scene.UnmarshalEntity(sd.StaticEntity)
	if err != nil {
		log.Printf("Error decoding static entity")
		return err
	}
	scene.StaticEntity = *staticEntity

	scene.Camera = sd.Camera
	scene.Space = sd.Space

	if scene.Entities == nil {
		scene.Entities = make(map[int]*Entity, 32)
	}

	for _, rawEntity := range sd.Entities {
		entity, err := scene.UnmarshalEntity(rawEntity)
		if err != nil {
			log.Printf("Error decoding entity")
			return err
		}
		scene.AddEntity(entity)
	}

	return nil
}

func (scene *Scene) UnmarshalEntity(data []byte) (*Entity, error) {
	type compData struct {<commit_msg>fixed static entity deserialization bug<commit_after>package mater

import (
	"bytes"
	"encoding/json"
	"github.com/teomat/mater/collision"
	"github.com/teomat/mater/transform"
	"log"
	"os"
)

var saveDirectory = "saves/"

func (mater *Mater) SaveScene(path string) error {
	scene := mater.Scene

	path = saveDirectory + path

	file, err := os.Create(path)
	if err != nil {
		log.Printf("Error opening File: %v", err)
		return err
	}
	defer file.Close()

	//encoder := json.NewEncoder(file)
	//err = encoder.Encode(scene)

	dataString, err := json.MarshalIndent(scene, "", "\t")
	if err != nil {
		log.Printf("Error encoding Scene: %v", err)
		return err
	}

	buf := bytes.NewBuffer(dataString)
	n, err := buf.WriteTo(file)
	if err != nil {
		log.Printf("Error after writing %v characters to File: %v", n, err)
		return err
	}

	return nil
}

func (mater *Mater) LoadScene(path string) error {

	var scene *Scene

	path = saveDirectory + path

	file, err := os.Open(path)
	if err != nil {
		log.Printf("Error opening File: %v", err)
		return err
	}
	defer file.Close()

	scene = new(Scene)
	cam := mater.DefaultCamera
	scene.Camera = &cam
	decoder := json.NewDecoder(file)

	err = decoder.Decode(scene)
	if err != nil {
		log.Printf("Error decoding Scene: %v", err)
		return err
	}

	mater.Scene.Destroy()

	mater.Scene = scene
	scene.Space.Enabled = true

	if mater.Scene.Camera == nil {
		cam := mater.DefaultCamera
		mater.Scene.Camera = &cam
	} else {
		mater.Scene.Camera.ScreenSize = mater.ScreenSize
	}

	mater.Dbg.DebugView.Reset(mater.Scene.Space)

	return nil
}

func (scene *Scene) MarshalJSON() ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	encoder := json.NewEncoder(buf)

	var err error

	buf.WriteString(`{"Camera":`)
	encoder.Encode(scene.Camera)

	buf.WriteString(`,"StaticEntity":`)
	encoder.Encode(&scene.StaticEntity)

	buf.WriteString(`,"Entities":`)
	entities, err := scene.MarshalEntities()
	if err != nil {
		return nil, err
	}
	buf.Write(entities)

	buf.WriteString(`,"Space":`)
	err = encoder.Encode(scene.Space)
	if err != nil {
		log.Printf("Error encoding scene")
		return nil, err
	}

	buf.WriteByte('}')

	return buf.Bytes(), nil
}

func (scene *Scene) MarshalEntities() ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	encoder := json.NewEncoder(buf)

	buf.WriteByte('[')
	for _, entity := range scene.Entities {

		err := encoder.Encode(entity)
		if err != nil {
			log.Printf("Error encoding entity")
			return nil, err
		}

		buf.WriteByte(',')
	}
	if len(scene.Entities) > 0 {
		//cut trailing comma
		buf.Truncate(buf.Len() - 1)
	}

	buf.WriteByte(']')

	return buf.Bytes(), nil
}

func (scene *Scene) UnmarshalJSON(data []byte) error {
	sceneData := struct {
		Camera       *Camera
		Space        *collision.Space
		StaticEntity json.RawMessage
		Entities     []json.RawMessage
	}{}

	err := json.Unmarshal(data, &sceneData)
	if err != nil {
		log.Printf("Error decoding scene")
		return err
	}

	sd := &sceneData

	scene.Space = sd.Space
	scene.Camera = sd.Camera

	staticEntity, err := scene.UnmarshalEntity(sd.StaticEntity)
	if err != nil {
		log.Printf("Error decoding static entity")
		return err
	}
	scene.StaticEntity = *staticEntity	

	if scene.Entities == nil {
		scene.Entities = make(map[int]*Entity, 32)
	}

	for _, rawEntity := range sd.Entities {
		entity, err := scene.UnmarshalEntity(rawEntity)
		if err != nil {
			log.Printf("Error decoding entity")
			return err
		}
		scene.AddEntity(entity)
	}

	return nil
}

func (scene *Scene) UnmarshalEntity(data []byte) (*Entity, error) {
	type compData struct {
{'fraction_non_alphanumeric': 0.14799154334038056, 'fraction_numerical': 0.001127554615926709, 'mean_word_length': 3.7180851063829787, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '542429', 'n_tokens_mistral': 2660, 'n_tokens_neox': 2499, 'n_words': 618}