// 📦 ConsBox - LISPのcons cell実装
// ペア（car, cdr）を表現する基本データ構造

box ConsBox {
    car    // 最初の要素
    cdr    // 残りの要素（通常は別のConsBoxかNullBox）
    
    init {
        car, cdr
    }
    
    // 基本アクセサ
    func getCar() {
        return me.car
    }
    
    func getCdr() {
        return me.cdr
    }
    
    func setCar(value) {
        me.car = value
    }
    
    func setCdr(value) {
        me.cdr = value
    }
    
    // リストかどうかの判定
    func isList() {
        // cdrがNullBoxならリストの終端
        if (NullBox.check_null(me.cdr)) {
            return true
        }
        // cdrがConsBoxなら再帰的にチェック
        // TODO: 型チェックの別の方法が必要
        // 暫定的にtrueを返す
        return true
        // それ以外はドット対
        return false
    }
    
    // リストの長さを取得
    func length() {
        if (not me.isList()) {
            return -1  // リストでない場合は-1
        }
        
        count = 0
        current = me
        loop(not NullBox.check_null(current)) {
            count = count + 1
            current = current.getCdr()
        }
        return count
    }
    
    // n番目の要素を取得（0ベース）
    func nth(n) {
        if (n < 0) {
            return new NullBox()
        }
        
        current = me
        i = 0
        loop(i < n) {
            if (NullBox.check_null(current)) {
                return new NullBox()
            }
            current = current.getCdr()
            i = i + 1
        }
        
        if (NullBox.check_null(current)) {
            return new NullBox()
        }
        return current.getCar()
    }
    
    // リストを配列に変換
    func toArray() {
        result = new ArrayBox()
        current = me
        
        loop(not NullBox.check_null(current)) {
            result.push(current.getCar())
            cdr = current.getCdr()
            
            // ドット対の場合
            // TODO: 型チェックの別の方法が必要
            // 暫定的にスキップ
            
            current = cdr
        }
        
        return result
    }
    
    // 文字列表現
    func toString() {
        // 空リスト
        if (NullBox.check_null(me.car) and NullBox.check_null(me.cdr)) {
            return "()"
        }
        
        result = "("
        current = me
        first = true
        
        loop(not NullBox.check_null(current)) {
            if (not first) {
                result = result + " "
            }
            first = false
            
            // carの表示
            car = current.getCar()
            if (NullBox.check_null(car)) {
                result = result + "nil"
            } else {
                result = result + car.toString()
            }
            
            // cdrの確認
            cdr = current.getCdr()
            if (NullBox.check_null(cdr)) {
                break
            }
            
            // ドット対の場合
            // TODO: 型チェックの別の方法が必要
            // 暫定的にスキップ
            
            current = cdr
        }
        
        result = result + ")"
        return result
    }
    
    // デバッグ用の詳細表示
    func debugPrint() {
        print("ConsBox {")
        print("  car: " + me.car.toString())
        print("  cdr: " + me.cdr.toString())
        print("  isList: " + me.isList())
        if (me.isList()) {
            print("  length: " + me.length())
        }
        print("}")
    }
}

// ヘルパー関数：配列からリストを作成
function arrayToList(arr) {
    if (arr.length() == 0) {
        return new NullBox()
    }
    
    // 逆順に構築
    result = new NullBox()
    i = arr.length() - 1
    loop(i >= 0) {
        result = new ConsBox(arr.get(i), result)
        i = i - 1
    }
    
    return result
}

// ヘルパー関数：可変長引数でリストを作成
function list() {
    // TODO: 可変長引数のサポートが必要
    // 現在は固定数の引数での実装例
    return new NullBox()
}

// テストコード
print("🎯 === ConsBox Test ===")

// 基本的なペア
print("📦 基本的なペア (1 . 2):")
pair = new ConsBox(new IntegerBox(1), new IntegerBox(2))
print(pair.toString())
pair.debugPrint()

// リスト (1 2 3)
print("\n📋 リスト (1 2 3):")
list123 = new ConsBox(
    new IntegerBox(1),
    new ConsBox(
        new IntegerBox(2),
        new ConsBox(
            new IntegerBox(3),
            new NullBox()
        )
    )
)
print(list123.toString())
print("Length: " + list123.length())
print("2nd element: " + list123.nth(1).toString())

// 配列からリストを作成
print("\n🔄 配列からリスト作成:")
arr = new ArrayBox()
arr.push(new StringBox("hello"))
arr.push(new StringBox("world"))
arr.push(new IntegerBox(42))
listFromArray = arrayToList(arr)
print(listFromArray.toString())

// ネストしたリスト ((1 2) (3 4))
print("\n🎯 ネストしたリスト:")
innerList1 = new ConsBox(
    new IntegerBox(1),
    new ConsBox(new IntegerBox(2), new NullBox())
)
innerList2 = new ConsBox(
    new IntegerBox(3),
    new ConsBox(new IntegerBox(4), new NullBox())
)
nestedList = new ConsBox(
    innerList1,
    new ConsBox(innerList2, new NullBox())
)
print(nestedList.toString())

print("\n✅ ConsBox implementation completed!")