// 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.

import 'package:flutter/material.dart';

import 'logic.dart';

class Calculator extends StatefulWidget {
  const Calculator({Key key}) : super(key: key);

  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {
  /// As the user taps keys we update the current `_expression` and we also
  /// keep a stack of previous expressions so we can return to earlier states
  /// when the user hits the DEL key.
  final List<CalcExpression> _expressionStack = <CalcExpression>[];
  CalcExpression _expression = CalcExpression.empty();

  // Make `expression` the current expression and push the previous current
  // expression onto the stack.
  void pushExpression(CalcExpression expression) {
    _expressionStack.add(_expression);
    _expression = expression;
  }

  /// Pop the top expression off of the stack and make it the current expression.
  void popCalcExpression() {
    if (_expressionStack.isNotEmpty) {
      _expression = _expressionStack.removeLast();
    } else {
      _expression = CalcExpression.empty();
    }
  }

  /// Set `resultExpression` to the current expression and clear the stack.
  void setResult(CalcExpression resultExpression) {
    _expressionStack.clear();
    _expression = resultExpression;
  }

  void handleNumberTap(int n) {
    final CalcExpression expression = _expression.appendDigit(n);
    if (expression != null) {
      setState(() {
        pushExpression(expression);
      });
    }
  }

  void handlePointTap() {
    final CalcExpression expression = _expression.appendPoint();
    if (expression != null) {
      setState(() {
        pushExpression(expression);
      });
    }
  }

  void handlePlusTap() {
    final CalcExpression expression = _expression.appendOperation(Operation.Addition);
    if (expression != null) {
      setState(() {
        pushExpression(expression);
      });
    }
  }

  void handleMinusTap() {
    final CalcExpression expression = _expression.appendMinus();
    if (expression != null) {
      setState(() {
        pushExpression(expression);
      });
    }
  }

  void handleMultTap() {
    final CalcExpression expression = _expression.appendOperation(Operation.Multiplication);
    if (expression != null) {
      setState(() {
        pushExpression(expression);
      });
    }
  }

  void handleDivTap() {
    final CalcExpression expression = _expression.appendOperation(Operation.Division);
    if (expression != null) {
      setState(() {
        pushExpression(expression);
      });
    }
  }

  void handleEqualsTap() {
    final CalcExpression resultExpression = _expression.computeResult();
    if (resultExpression != null) {
      setState(() {
        setResult(resultExpression);
      });
    }
  }

  void handleDelTap() {
    setState(() {
      popCalcExpression();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).canvasColor,
        elevation: 0.0,
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          // Give the key-pad 3/5 of the vertical space and the display 2/5.
          Expanded(
            flex: 2,
            child: CalcDisplay(content: _expression.toString()),
          ),
          const Divider(height: 1.0),
          Expanded(
            flex: 3,
            child: KeyPad(calcState: this),
          ),
        ],
      ),
    );
  }
}

class CalcDisplay extends StatelessWidget {
  const CalcDisplay({ this.content });

  final String content;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        content,
        style: const TextStyle(fontSize: 24.0),
      ),
    );
  }
}

class KeyPad extends StatelessWidget {
  const KeyPad({ this.calcState });

  final _CalculatorState calcState;

  @override
  Widget build(BuildContext context) {
    final ThemeData themeData = ThemeData(
      primarySwatch: Colors.purple,
      brightness: Brightness.dark,
      platform: Theme.of(context).platform,
    );
    return Theme(
      data: themeData,
      child: Material(
        child: Row(
          children: <Widget>[
            Expanded(
              // We set flex equal to the number of columns so that the main keypad
              // and the op keypad have sizes proportional to their number of
              // columns.
              flex: 3,
              child: Column(
                children: <Widget>[
                  KeyRow(<Widget>[
                    NumberKey(7, calcState),
                    NumberKey(8, calcState),
                    NumberKey(9, calcState),
                  ]),
                  KeyRow(<Widget>[
                    NumberKey(4, calcState),
                    NumberKey(5, calcState),
                    NumberKey(6, calcState),
                  ]),
                  KeyRow(<Widget>[
                    NumberKey(1, calcState),
                    NumberKey(2, calcState),
                    NumberKey(3, calcState),
                  ]),
                  KeyRow(<Widget>[
                    CalcKey('.', calcState.handlePointTap),
                    NumberKey(0, calcState),
                    CalcKey('=', calcState.handleEqualsTap),
                  ]),
                ],
              ),
            ),
            Expanded(
              child: Material(
                color: themeData.backgroundColor,
                child: Column(
                  children: <Widget>[
                    CalcKey('\u232B', calcState.handleDelTap),
                    CalcKey('\u00F7', calcState.handleDivTap),
                    CalcKey('\u00D7', calcState.handleMultTap),
                    CalcKey('-', calcState.handleMinusTap),
                    CalcKey('+', calcState.handlePlusTap),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class KeyRow extends StatelessWidget {
  const KeyRow(this.keys);

  final List<Widget> keys;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: keys,
      ),
    );
  }
}

class CalcKey extends StatelessWidget {
  const CalcKey(this.text, this.onTap);

  final String text;
  final GestureTapCallback onTap;

  @override
  Widget build(BuildContext context) {
    final Orientation orientation = MediaQuery.of(context).orientation;
    return Expanded(
      child: InkResponse(
        onTap: onTap,
        child: Center(
          child: Text(
            text,
            style: TextStyle(
              fontSize: (orientation == Orientation.portrait) ? 32.0 : 24.0
            ),
          ),
        ),
      ),
    );
  }
}

class NumberKey extends CalcKey {
  NumberKey(int value, _CalculatorState calcState)
    : super('$value', () {
        calcState.handleNumberTap(value);
      });
}
