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

// Flutter code sample for [CupertinoFormRow].

import 'package:flutter/cupertino.dart';

void main() => runApp(const CupertinoFormRowApp());

class CupertinoFormRowApp extends StatelessWidget {
  const CupertinoFormRowApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      theme: CupertinoThemeData(brightness: Brightness.light),
      home: CupertinoFormRowExample(),
    );
  }
}

class CupertinoFormRowExample extends StatefulWidget {
  const CupertinoFormRowExample({super.key});

  @override
  State<CupertinoFormRowExample> createState() => _CupertinoFormRowExampleState();
}

class _CupertinoFormRowExampleState extends State<CupertinoFormRowExample> {
  bool airplaneMode = false;

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('CupertinoFormSection Sample'),
      ),
      // Add safe area widget to place the CupertinoFormSection below the navigation bar.
      child: SafeArea(
        child: CupertinoFormSection(
          header: const Text('Connectivity'),
          children: <Widget>[
            CupertinoFormRow(
              prefix: const PrefixWidget(
                icon: CupertinoIcons.airplane,
                title: 'Airplane Mode',
                color: CupertinoColors.systemOrange,
              ),
              child: CupertinoSwitch(
                value: airplaneMode,
                onChanged: (bool value) {
                  setState(() {
                    airplaneMode = value;
                  });
                },
              ),
            ),
            CupertinoFormRow(
              prefix: const PrefixWidget(
                icon: CupertinoIcons.wifi,
                title: 'Wi-Fi',
                color: CupertinoColors.systemBlue,
              ),
              error: const Text('Home network unavailable'),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: const <Widget>[
                  Text('Not connected'),
                  SizedBox(width: 5),
                  Icon(CupertinoIcons.forward)
                ],
              ),
            ),
            CupertinoFormRow(
              prefix: const PrefixWidget(
                icon: CupertinoIcons.bluetooth,
                title: 'Bluetooth',
                color: CupertinoColors.activeBlue,
              ),
              helper: Padding(
                padding: const EdgeInsets.symmetric(vertical: 4.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: const <Widget>[
                    Text('Headphone'),
                    Text('Connected'),
                  ],
                ),
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: const <Widget>[
                  Text('On'),
                  SizedBox(width: 5),
                  Icon(CupertinoIcons.forward)
                ],
              ),
            ),
            const CupertinoFormRow(
              prefix: PrefixWidget(
                icon: CupertinoIcons.bluetooth,
                title: 'Mobile Data',
                color: CupertinoColors.systemGreen,
              ),
              child: Icon(CupertinoIcons.forward),
            ),
          ],
        ),
      ),
    );
  }
}

class PrefixWidget extends StatelessWidget {
  const PrefixWidget({
    super.key,
    required this.icon,
    required this.title,
    required this.color,
  });

  final IconData icon;
  final String title;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Container(
          padding: const EdgeInsets.all(4.0),
          decoration: BoxDecoration(
            color: color,
            borderRadius: BorderRadius.circular(4.0),
          ),
          child: Icon(icon, color: CupertinoColors.white),
        ),
        const SizedBox(width: 15),
        Text(title)
      ],
    );
  }
}
