/* **********************************************************************************
 *
 * Copyright (c) Microsoft Corporation. All rights reserved.
 *
 * This source code is subject to terms and conditions of the Shared Source License
 * for IronPython. A copy of the license can be found in the License.html file
 * at the root of this distribution. If you can not locate the Shared Source License
 * for IronPython, please send an email to ironpy@microsoft.com.
 * By using this source code in any fashion, you are agreeing to be bound by
 * the terms of the Shared Source License for IronPython.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * **********************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

namespace IronPythonTest {
    public struct MySize {
        public int width;
        public int height;

        public MySize(int w, int h) {
            width = w;
            height = h;
        }
    }

    public class BaseClassStaticConstructor {
        static int value;
        static BaseClassStaticConstructor() {
            value = 10;
        }

        public int Value {
            get {
                return value;
            }
        }
    }

    public class BaseClass {
        public MySize size;
        protected int foo;

        public BaseClass()
            : this(0, 0) {
        }

        public BaseClass(MySize size) {
            this.size = size;
        }

        public BaseClass(int width, int height)
            : this(new MySize(width, height)) {
        }

        public MySize Size {
            get {
                return size;
            }
            set {
                size = value;
            }
        }

        public int Height {
            get {
                return size.height;
            }
            set {
                size.height = value;
            }
        }

        public int Width {
            get {
                return size.width;
            }
            set {
                size.width = value;
            }
        }

        /// <summary>
        /// mixed access property
        /// </summary>
        public int Area {
            get {
                return size.width * size.height;
            }
            protected set {
                if (size.width != 0) {
                    size.height = value / size.width;
                } else if (size.height != 0) {
                    size.width = value / size.height;
                } else {
                    size.width = size.height = (int)Math.Round(Math.Sqrt(value));
                }
            }
        }

        protected string ProtectedMethod() {
            return "BaseClass.Protected";
        }
    }

    public class BindingTestClass {
        public static object Bind(bool parm) {
            return parm;
        }

        public static object Bind(string parm) {
            return parm;
        }

        public static object Bind(int parm) {
            return parm;
        }
    }

    public class InheritedBindingBase {
        public virtual object Bind(bool parm) {
            return "Base bool";
        }

        public virtual object Bind(string parm) {
            return "Base string";
        }

        public virtual object Bind(int parm) {
            return "Base int";
        }
    }

    public class InheritedBindingSub : InheritedBindingBase {
        public override object Bind(bool parm) {
            return "Subclass bool";
        }
        public override object Bind(string parm) {
            return "Subclass string";
        }
        public override object Bind(int parm) {
            return "Subclass int";
        }
    }

    public class Infinite {
        public virtual object __cmp__(object other) {
            return true;
        }
    }

    public abstract class Overriding {
        string protVal = "Overriding.Protected";

        public virtual object __cmp__(object other) {
            return "Overriding.__cmp__(object)";
        }
        public virtual object __cmp__(string other) {
            return "Overriding.__cmp__(string)";
        }
        public virtual object __cmp__(double other) {
            return "Overriding.__cmp__(double)";
        }
        public virtual object __cmp__(int other) {
            return "Overriding.__cmp__(int)";
        }
        public virtual string TopMethod() {
            return TemplateMethod() + " - and Top";
        }

        public virtual string TemplateMethod() {
            return "From Base";
        }

        public virtual string BigTopMethod() {
            return BigTemplateMethod(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + " - and Top";
        }

        public virtual string BigTemplateMethod(int a0, int a1, int a2, int a3, int a4, int a5, object a6, object a7, object a8, object a9) {
            return "BaseBigTemplate";
        }

        public virtual string AbstractTopMethod() {
            return AbstractTemplateMethod() + " - and Top";
        }

        public abstract string AbstractTemplateMethod();

        protected virtual string ProtectedMethod() {
            return "Overriding.ProtectedMethod";
        }

        public string CallProtected() {
            return ProtectedMethod();
        }

        protected virtual string ProtectedProperty {
            get {
                return protVal;
            }
            set {
                protVal = value;
            }
        }

        public string CallProtectedProp() {
            return ProtectedProperty;
        }

        public void SetProtectedProp(string val) {
            ProtectedProperty = val;
        }

        /// <summary>
        /// not defined in Inherited
        /// </summary>
        public virtual string SkippedProperty {
            get {
                return "Skipped";
            }
        }
    }

    public class Inherited : Overriding {
        private String str;
        public Inherited() {
            this.str = TopMethod();
        }

        public override string AbstractTemplateMethod() {
            throw new Exception("The method or operation is not implemented.");
        }

        protected override string ProtectedMethod() {
            return "Inherited.ProtectedMethod";
        }

        protected override string ProtectedProperty {
            get {
                return "Inherited.Protected";
            }
            set {
                base.ProtectedProperty = value;
            }
        }
    }

    public interface ITestIt1 {
        object Method();
    }

    public interface ITestIt2 {
        object Method(int n);
    }

    public interface ITestIt3 {
        string Name {
            get;
        }
    }

    public class TestIt {
        public static object DoIt1(ITestIt1 o) {
            return o.Method();
        }
        public static object DoIt2(ITestIt2 o) {
            return o.Method(42);
        }
    }

    public class MoreOverridding {
        public virtual object Test1(params object[] args) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < args.Length; i++) {
                sb.Append(args[i]);
            }
            return "C# Test1" + sb.ToString();
        }

        public virtual object Test2(object x, params object[] args) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < args.Length; i++) {
                sb.Append(args[i]);
            }
            return "C# Test2" + sb.ToString();
        }

        public virtual object Test3(ref object x) {
            return "C# Test3";
        }

        public virtual object Test4(object x, ref object y) {
            return "C# Test4";
        }

        public virtual object Test5(StringComparison sc) {
            return "C# Test5" + sc.ToString();
        }

        public virtual object Test6(object x, StringComparison sc) {
            return "C# Test6" + x.ToString() + sc.ToString();
        }
        public object CallTest1() {
            return Test1("aa", "bb");
        }
        public object CallTest2() {
            return Test2("aa", "bb", "cc");
        }
        public object CallTest3() {
            object x = null;
            return Test3(ref x);
        }
        public object CallTest4() {
            object y = null;
            return Test4("aa", ref y);
        }

        public object CallTest5() {
            return Test5(StringComparison.Ordinal);
        }

        public object CallTest6() {
            return Test6("aa", StringComparison.Ordinal);
        }
    }

    public abstract class CliAbstractClass {
        public static int helperF;

        public static void MS(int x) { helperF = -2 * x; }
        public void MI(int x) { helperF = -3 * x; }
        public virtual void MV(int x) { helperF = -4 * x; }
        public abstract void MA(int x);
    }

    public interface CliInterface {
        void M1();
        int M2(int x);
    }

    public class UseCliClass {
        public void AsParam10(CliInterface itf) { itf.M1(); }
        public void AsParam11(CliInterface itf, int x) { itf.M2(x); }

        public void AsParam20(CliAbstractClass abs, int x) { abs.MV(x); }
        public void AsParam21(CliAbstractClass abs, int x) { abs.MA(x); }
        public void AsParam22(CliAbstractClass abs, int x) { CliAbstractClass.MS(x); }
        public void AsParam23(CliAbstractClass abs, int x) { abs.MI(x); }

        public CliInterface AsRetVal10(CliInterface itf) { return itf; }
    }

    public class CliVirtualStuff {
        private int m_var;
        public virtual int VirtualProperty {
            get { return m_var; }
            set { m_var = value; }
        }

        public virtual int VirtualMethod(int x) { return 10 * x; }

        protected virtual int VirtualProtectedProperty {
            get { return m_var; }
            set { m_var = value; }
        }

        protected virtual int VirtualProtectedMethod() { return -10; }

        public bool ProtectedStuffCheckHelper(int var, int ret) {
            return (VirtualProtectedMethod() == ret) && (VirtualProtectedProperty == var);
        }

        public bool PublicStuffCheckHelper(int var, int ret) {
            return (VirtualMethod(10) == ret) && (VirtualProperty == var);
        }
    }

    public class CtorTest {
        public int CtorRan;
        public object [] vals;
        public CtorTest() {
            CtorRan = -1;
        }

        public CtorTest(int a, int b, int c) {
            CtorRan = 0;
            vals = new object[] { a, b, c };
        }

        public CtorTest(string a, string b, string c) {
            CtorRan = 1;
            vals = new object[] { a, b, c };
        }

        public CtorTest(string a) {
            CtorRan = 2;
            vals = new object[] { a };
        }

        public CtorTest(object a) {
            CtorRan = 3;
            vals = new object[] { a };
        }
    }
}



