/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.wicket.examples.compref;

import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.examples.WicketExamplePage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.PropertyModel;

/**
 * Page with examples on {@link org.apache.wicket.markup.html.link.Link}.
 * 
 * @author Eelco Hillenius
 */
public class LinkPage extends WicketExamplePage
{
    /**
     * Constructor
     */
    public LinkPage()
    {
        // power to the annonymous classes!

        // first create a simple value holder object
        final Count count1 = new Count();

        // add a link which, when clicked, increases our counter when a link is clicked, its onClick
        // method is called
        Link<Void> link1 = new Link<Void>("link1") {
            public void onClick() {
                count1.increment();
            }
        };
        add(link1);

        // add a counter label to the link so that we can display it in the body of the link
        link1.add(new Label("label1", count1::toString));

        final Count count2 = new Count();
        // Same idea as above, but now we record a state change. Note that the URL will change
        // because of this, and pressing the back button and clicking the link again would revert to
        // the older value. The same thing could have been achieved by using setModelObject,
        // which implicitly registers a state change (of type ComponentModelChange).
        Link<Void> linkWithStateChange = new Link<Void>("linkWithStateChange") {
            @Override
            public void onClick()
            {
                count2.increment();
                addStateChange();
            }
        };
        add(linkWithStateChange);
        linkWithStateChange.add(new Label("label", new PropertyModel<>(count2, "count")));

        // we can attach Link components to any HTML tag we want. If it is an anchor (<a href...),
        // the url to this component is put in the href attribute. For other components, a onclick
        // javascript event handler is created that triggers the round trip

        // it is of course possible to - instead of the above approach - hide as much of the
        // component as possible within a class.
        class CustomLink extends Link<Void>
        {
            final Count count2;

            /**
             * Construct.
             * 
             * @param id
             */
            public CustomLink(String id)
            {
                super(id);
                count2 = new Count();
                add(new ClickCountLabel("label2", count2));
            }

            @Override
            public void onClick()
            {
                count2.increment();
            }
        }
        add(new CustomLink("link2"));

        // and if we know we are going to attach it to a <input type="button> tag, we shouldn't use
        // a label, but an AttributeModifier instead.
        class ButtonLink extends Link<Void>
        {
            final Count count3;

            /**
             * Construct.
             * 
             * @param id
             */
            public ButtonLink(String id)
            {
                super(id);
                count3 = new Count();
                add(Behavior.onAttribute("value", oldValue -> "this button is clicked " + count3.getCount() + " times"));
            }

            @Override
            public void onClick()
            {
                count3.increment();
            }
        }
        add(new ButtonLink("link3"));
    }

    /**
     * Simple custom label that displays the link click count.
     */
    private static class ClickCountLabel extends Label
    {
        /**
         * Construct.
         * 
         * @param id
         *            component id
         * @param clickCount
         *            the count object
         */
        public ClickCountLabel(String id, final Count clickCount)
        {
            // call super with a simple lambda model that displays the
            // current number of clicks
            super(id, clickCount::toString);
        }
    }

    /**
     * Override base method to provide an explanation
     */
    @Override
    protected void explain()
    {
        String html = "<a href=\"#\" wicket:id=\"link1\">this link is clicked <span wicket:id=\"label1\">n</span> times</a>";
        String code = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final Count count1 = new Count(); // simple counter object\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Link link1 = new Link(\"link1\") {\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClick() {\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count1.increment();\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;link1.add(new Label(\"label1\", new Model&lt;String&gt;() {\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Object getObject() {\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return count1.toString();\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n"
            + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add(link1);";
        add(new ExplainPanel(html, code));

    }
}