﻿using Mp4BoxViewer.Model.Boxes;
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace Mp4BoxViewer.Model
{
    public static class BoxFactory
    {
        /// <summary>
        /// BOXを生成する
        /// </summary>
        /// <param name="fs">ファイルストリーム</param>
        /// <param name="offset">BOXの開始オフセット</param>
        /// <returns>BOX</returns>
        public static Box CreateBox(FileStream fs, long offset, Box parent = null)
        {
            if (offset + 8 >= fs.Length) { return null; }
            fs.Seek(offset, SeekOrigin.Begin);

            UInt32 size = Mp4Util.getUint32Number(fs);
            string name = Mp4Util.getAsciiString(fs);

            if (size == 0 || !Regex.IsMatch(name, @"[a-zA-Z0-9@]{4}")) { return null; }

            // BOXの生成
            // TODO 多くなりそうなので別メソッド化
            Box box = null;
            switch (name)
            {
                case "ftyp":
                    box = new FileTypeBox(parent);
                    break;
                case "mvhd":
                    box = new MovieHeaderBox(parent);
                    break;
                case "hdlr":
                    box = new HandlerReferenceBox(parent);
                    break;
                case "tkhd":
                    box = new TrackHeaderBox(parent);
                    break;
                case "stsd":
                    box = new SampleDescriptionBox(parent);
                    break;
                case "uuid":
                    box = new UuidBox(parent);
                    break;
                default:
                    box = new Box(parent);
                    break;
            }

            // 共通情報設定
            box.Name = name;
            box.Size = (UInt64)size;
            box.IsExtensionSize = false;
            box.Offset = (UInt64)offset;

            // サイズが"1"なら拡張サイズを設定
            if (box.Size == 1)
            {
                box.IsExtensionSize = true;
                box.Size = Mp4Util.getUint64Number(fs);
            }

            // BOX固有の解析
            box.StructUniqueParameters(fs);

            return box;
        }
    }
}
