/*
 ** 2013 June 16
 **
 ** The author disclaims copyright to this source code.  In place of
 ** a legal notice, here is a blessing:
 **    May you do good and not evil.
 **    May you find forgiveness for yourself and forgive others.
 **    May you share freely, never taking more than you give.
 */
package info.ata4.unity.asset;

import info.ata4.io.DataInputReader;
import info.ata4.io.DataOutputWriter;
import info.ata4.io.Struct;
import info.ata4.unity.util.UnityVersion;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Class that holds the runtime type information of an asset file.
 * 
 * @author Nico Bergemann <barracuda415 at yahoo.de>
 */
public class FieldTypeTree implements Struct {

    private final Map<Integer, FieldTypeNode> typeMap = new LinkedHashMap<>();
    private final AssetVersionInfo versionInfo;
    private UnityVersion unityRevision;
    private int treeVersion;
    
    public FieldTypeTree(AssetVersionInfo versionInfo) {
        this.versionInfo = versionInfo;
    }

    public Map<Integer, FieldTypeNode> getFields() {
        return typeMap;
    }
    
    public UnityVersion getUnityRevision() {
        return unityRevision;
    }

    public void setUnityRevision(UnityVersion unityRevision) {
        this.unityRevision = unityRevision;
    }

    public int getVersion() {
        return treeVersion;
    }

    public void setVersion(int version) {
        this.treeVersion = version;
    }

    @Override
    public void read(DataInputReader in) throws IOException {
        // revision/version for newer formats
        if (versionInfo.getAssetVersion() >= 7) {
            unityRevision = new UnityVersion(in.readStringNull(255));
            treeVersion = in.readInt();
        }
        
        in.setSwap(versionInfo.swapRequired());
        
        int fields = in.readInt();
        for (int i = 0; i < fields; i++) {
            int classID = in.readInt();

            FieldTypeNode node = new FieldTypeNode();
            node.read(in);
            
            typeMap.put(classID, node);
        }
        
        // padding
        if (versionInfo.getAssetVersion() >= 7) {
            in.readInt();
        }
    }

    @Override
    public void write(DataOutputWriter out) throws IOException {
        // revision/version for newer formats
        if (versionInfo.getAssetVersion() >= 7) {
            out.writeStringNull(unityRevision.toString());
            out.writeInt(treeVersion);
        }
        
        out.setSwap(versionInfo.swapRequired());
        
        if (typeMap.isEmpty()) {
            int fields = typeMap.size();
            out.writeInt(fields);

            for (Map.Entry<Integer, FieldTypeNode> entry : typeMap.entrySet()) {
                int classID = entry.getKey();
                out.writeInt(classID);
                
                FieldTypeNode node = entry.getValue();
                node.write(out);
            }
        } else {
            out.writeInt(0);
        }
        
        // padding
        if (versionInfo.getAssetVersion() >= 7) {
            out.writeInt(0);
        }
    }
    
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FieldTypeTree other = (FieldTypeTree) obj;
        if (!Objects.equals(this.typeMap, other.typeMap)) {
            return false;
        }
        if (!Objects.equals(this.unityRevision, other.unityRevision)) {
            return false;
        }
        if (this.treeVersion != other.treeVersion) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 29 * hash + Objects.hashCode(this.typeMap);
        hash = 29 * hash + Objects.hashCode(this.unityRevision);
        hash = 29 * hash + this.treeVersion;
        return hash;
    }
}
@@ -891,48 +891,9 @@
 fo;%0A
-    private UnityVersion unityRevision;
 %0A
+
     
@@ -1174,17 +1174,32 @@
  return 
-u
+versionInfo.getU
 nityRevi
@@ -1194,32 +1194,34 @@
 getUnityRevision
+()
 ;%0A    %7D%0A%0A    pub
@@ -1284,22 +1284,32 @@
         
-this.u
+versionInfo.setU
 nityRevi
@@ -1312,19 +1312,17 @@
 Revision
- = 
+(
 unityRev
@@ -1322,24 +1322,25 @@
 nityRevision
+)
 ;%0A    %7D%0A%0A   
@@ -1670,17 +1670,32 @@
         
-u
+versionInfo.setU
 nityRevi
@@ -1698,19 +1698,17 @@
 Revision
- = 
+(
 new Unit
@@ -1739,16 +1739,17 @@
 ll(255))
+)
 ;%0A      
@@ -2449,17 +2449,32 @@
 ingNull(
-u
+versionInfo.getU
 nityRevi
@@ -2477,16 +2477,18 @@
 Revision
+()
 .toStrin
@@ -3566,25 +3566,40 @@
 equals(this.
-u
+versionInfo.getU
 nityRevision
@@ -3598,24 +3598,26 @@
 Revision
+()
 , other.
 unityRev
@@ -3608,17 +3608,32 @@
 , other.
-u
+versionInfo.getU
 nityRevi
@@ -3636,16 +3636,18 @@
 Revision
+()
 )) %7B%0A   
@@ -3968,17 +3968,32 @@
 de(this.
-u
+versionInfo.getU
 nityRevi
@@ -3992,24 +3992,26 @@
 nityRevision
+()
 );%0A        h

Use revision from versionInfo